]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1da177e4 LT |
2 | /* |
3 | * linux/fs/lockd/xdr4.c | |
4 | * | |
5 | * XDR support for lockd and the lock client. | |
6 | * | |
7 | * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> | |
8 | * Copyright (C) 1999, Trond Myklebust <trond.myklebust@fys.uio.no> | |
9 | */ | |
10 | ||
11 | #include <linux/types.h> | |
12 | #include <linux/sched.h> | |
1da177e4 LT |
13 | #include <linux/nfs.h> |
14 | ||
15 | #include <linux/sunrpc/xdr.h> | |
16 | #include <linux/sunrpc/clnt.h> | |
17 | #include <linux/sunrpc/svc.h> | |
18 | #include <linux/sunrpc/stats.h> | |
19 | #include <linux/lockd/lockd.h> | |
1da177e4 | 20 | |
7956521a CL |
21 | #include "svcxdr.h" |
22 | ||
1da177e4 LT |
23 | static inline s64 |
24 | loff_t_to_s64(loff_t offset) | |
25 | { | |
26 | s64 res; | |
27 | if (offset > NLM4_OFFSET_MAX) | |
28 | res = NLM4_OFFSET_MAX; | |
29 | else if (offset < -NLM4_OFFSET_MAX) | |
30 | res = -NLM4_OFFSET_MAX; | |
31 | else | |
32 | res = offset; | |
33 | return res; | |
34 | } | |
35 | ||
345b4159 CL |
36 | /* |
37 | * NLM file handles are defined by specification to be a variable-length | |
38 | * XDR opaque no longer than 1024 bytes. However, this implementation | |
39 | * limits their length to the size of an NFSv3 file handle. | |
40 | */ | |
41 | static bool | |
42 | svcxdr_decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh) | |
43 | { | |
44 | __be32 *p; | |
45 | u32 len; | |
46 | ||
47 | if (xdr_stream_decode_u32(xdr, &len) < 0) | |
48 | return false; | |
49 | if (len > NFS_MAXFHSIZE) | |
50 | return false; | |
51 | ||
52 | p = xdr_inline_decode(xdr, len); | |
53 | if (!p) | |
54 | return false; | |
55 | fh->size = len; | |
56 | memcpy(fh->data, p, len); | |
57 | memset(fh->data + len, 0, sizeof(fh->data) - len); | |
58 | ||
59 | return true; | |
60 | } | |
61 | ||
345b4159 CL |
62 | static bool |
63 | svcxdr_decode_lock(struct xdr_stream *xdr, struct nlm_lock *lock) | |
64 | { | |
65 | struct file_lock *fl = &lock->fl; | |
345b4159 CL |
66 | |
67 | if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len)) | |
68 | return false; | |
69 | if (!svcxdr_decode_fhandle(xdr, &lock->fh)) | |
70 | return false; | |
71 | if (!svcxdr_decode_owner(xdr, &lock->oh)) | |
72 | return false; | |
73 | if (xdr_stream_decode_u32(xdr, &lock->svid) < 0) | |
74 | return false; | |
6930bcbf | 75 | if (xdr_stream_decode_u64(xdr, &lock->lock_start) < 0) |
345b4159 | 76 | return false; |
6930bcbf | 77 | if (xdr_stream_decode_u64(xdr, &lock->lock_len) < 0) |
345b4159 CL |
78 | return false; |
79 | ||
80 | locks_init_lock(fl); | |
81 | fl->fl_flags = FL_POSIX; | |
82 | fl->fl_type = F_RDLCK; | |
345b4159 CL |
83 | |
84 | return true; | |
85 | } | |
86 | ||
1beef147 CL |
87 | static bool |
88 | svcxdr_encode_holder(struct xdr_stream *xdr, const struct nlm_lock *lock) | |
1da177e4 | 89 | { |
1beef147 CL |
90 | const struct file_lock *fl = &lock->fl; |
91 | s64 start, len; | |
1da177e4 | 92 | |
1beef147 CL |
93 | /* exclusive */ |
94 | if (xdr_stream_encode_bool(xdr, fl->fl_type != F_RDLCK) < 0) | |
95 | return false; | |
96 | if (xdr_stream_encode_u32(xdr, lock->svid) < 0) | |
97 | return false; | |
98 | if (!svcxdr_encode_owner(xdr, &lock->oh)) | |
99 | return false; | |
100 | start = loff_t_to_s64(fl->fl_start); | |
101 | if (fl->fl_end == OFFSET_MAX) | |
102 | len = 0; | |
103 | else | |
104 | len = loff_t_to_s64(fl->fl_end - fl->fl_start + 1); | |
105 | if (xdr_stream_encode_u64(xdr, start) < 0) | |
106 | return false; | |
107 | if (xdr_stream_encode_u64(xdr, len) < 0) | |
108 | return false; | |
109 | ||
110 | return true; | |
111 | } | |
1da177e4 | 112 | |
1beef147 CL |
113 | static bool |
114 | svcxdr_encode_testrply(struct xdr_stream *xdr, const struct nlm_res *resp) | |
115 | { | |
116 | if (!svcxdr_encode_stats(xdr, resp->status)) | |
117 | return false; | |
118 | switch (resp->status) { | |
119 | case nlm_lck_denied: | |
120 | if (!svcxdr_encode_holder(xdr, &resp->lock)) | |
121 | return false; | |
1da177e4 LT |
122 | } |
123 | ||
1beef147 | 124 | return true; |
1da177e4 LT |
125 | } |
126 | ||
127 | ||
128 | /* | |
7956521a | 129 | * Decode Call arguments |
1da177e4 | 130 | */ |
7956521a | 131 | |
c44b31c2 | 132 | bool |
16c66364 | 133 | nlm4svc_decode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr) |
7956521a | 134 | { |
c44b31c2 | 135 | return true; |
7956521a CL |
136 | } |
137 | ||
c44b31c2 | 138 | bool |
16c66364 | 139 | nlm4svc_decode_testargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) |
1da177e4 | 140 | { |
026fec7e | 141 | struct nlm_args *argp = rqstp->rq_argp; |
345b4159 | 142 | u32 exclusive; |
1da177e4 | 143 | |
345b4159 | 144 | if (!svcxdr_decode_cookie(xdr, &argp->cookie)) |
c44b31c2 | 145 | return false; |
345b4159 | 146 | if (xdr_stream_decode_bool(xdr, &exclusive) < 0) |
c44b31c2 | 147 | return false; |
345b4159 | 148 | if (!svcxdr_decode_lock(xdr, &argp->lock)) |
c44b31c2 | 149 | return false; |
1da177e4 LT |
150 | if (exclusive) |
151 | argp->lock.fl.fl_type = F_WRLCK; | |
152 | ||
c44b31c2 | 153 | return true; |
1da177e4 LT |
154 | } |
155 | ||
c44b31c2 | 156 | bool |
16c66364 | 157 | nlm4svc_decode_lockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) |
1da177e4 | 158 | { |
026fec7e | 159 | struct nlm_args *argp = rqstp->rq_argp; |
0e5977af | 160 | u32 exclusive; |
1da177e4 | 161 | |
0e5977af | 162 | if (!svcxdr_decode_cookie(xdr, &argp->cookie)) |
c44b31c2 | 163 | return false; |
0e5977af | 164 | if (xdr_stream_decode_bool(xdr, &argp->block) < 0) |
c44b31c2 | 165 | return false; |
0e5977af | 166 | if (xdr_stream_decode_bool(xdr, &exclusive) < 0) |
c44b31c2 | 167 | return false; |
0e5977af | 168 | if (!svcxdr_decode_lock(xdr, &argp->lock)) |
c44b31c2 | 169 | return false; |
1da177e4 LT |
170 | if (exclusive) |
171 | argp->lock.fl.fl_type = F_WRLCK; | |
0e5977af | 172 | if (xdr_stream_decode_bool(xdr, &argp->reclaim) < 0) |
c44b31c2 | 173 | return false; |
0e5977af | 174 | if (xdr_stream_decode_u32(xdr, &argp->state) < 0) |
c44b31c2 | 175 | return false; |
1da177e4 LT |
176 | argp->monitor = 1; /* monitor client by default */ |
177 | ||
c44b31c2 | 178 | return true; |
0e5977af CL |
179 | } |
180 | ||
c44b31c2 | 181 | bool |
16c66364 | 182 | nlm4svc_decode_cancargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) |
0e5977af | 183 | { |
1e1f38dc CL |
184 | struct nlm_args *argp = rqstp->rq_argp; |
185 | u32 exclusive; | |
0e5977af | 186 | |
1e1f38dc | 187 | if (!svcxdr_decode_cookie(xdr, &argp->cookie)) |
c44b31c2 | 188 | return false; |
1e1f38dc | 189 | if (xdr_stream_decode_bool(xdr, &argp->block) < 0) |
c44b31c2 | 190 | return false; |
1e1f38dc | 191 | if (xdr_stream_decode_bool(xdr, &exclusive) < 0) |
c44b31c2 | 192 | return false; |
1e1f38dc | 193 | if (!svcxdr_decode_lock(xdr, &argp->lock)) |
c44b31c2 | 194 | return false; |
1e1f38dc CL |
195 | if (exclusive) |
196 | argp->lock.fl.fl_type = F_WRLCK; | |
c44b31c2 CL |
197 | |
198 | return true; | |
1da177e4 LT |
199 | } |
200 | ||
c44b31c2 | 201 | bool |
16c66364 | 202 | nlm4svc_decode_unlockargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) |
1da177e4 | 203 | { |
d76d8c25 | 204 | struct nlm_args *argp = rqstp->rq_argp; |
1da177e4 | 205 | |
d76d8c25 | 206 | if (!svcxdr_decode_cookie(xdr, &argp->cookie)) |
c44b31c2 | 207 | return false; |
d76d8c25 | 208 | if (!svcxdr_decode_lock(xdr, &argp->lock)) |
c44b31c2 | 209 | return false; |
d76d8c25 CL |
210 | argp->lock.fl.fl_type = F_UNLCK; |
211 | ||
c44b31c2 | 212 | return true; |
1da177e4 LT |
213 | } |
214 | ||
c44b31c2 | 215 | bool |
16c66364 | 216 | nlm4svc_decode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr) |
b4c24b5a | 217 | { |
b4c24b5a CL |
218 | struct nlm_res *resp = rqstp->rq_argp; |
219 | ||
220 | if (!svcxdr_decode_cookie(xdr, &resp->cookie)) | |
c44b31c2 | 221 | return false; |
b4c24b5a | 222 | if (!svcxdr_decode_stats(xdr, &resp->status)) |
c44b31c2 | 223 | return false; |
b4c24b5a | 224 | |
c44b31c2 | 225 | return true; |
b4c24b5a CL |
226 | } |
227 | ||
c44b31c2 | 228 | bool |
16c66364 | 229 | nlm4svc_decode_reboot(struct svc_rqst *rqstp, struct xdr_stream *xdr) |
bc3665fd | 230 | { |
bc3665fd | 231 | struct nlm_reboot *argp = rqstp->rq_argp; |
16c66364 | 232 | __be32 *p; |
bc3665fd CL |
233 | u32 len; |
234 | ||
235 | if (xdr_stream_decode_u32(xdr, &len) < 0) | |
c44b31c2 | 236 | return false; |
bc3665fd | 237 | if (len > SM_MAXSTRLEN) |
c44b31c2 | 238 | return false; |
bc3665fd CL |
239 | p = xdr_inline_decode(xdr, len); |
240 | if (!p) | |
c44b31c2 | 241 | return false; |
bc3665fd CL |
242 | argp->len = len; |
243 | argp->mon = (char *)p; | |
244 | if (xdr_stream_decode_u32(xdr, &argp->state) < 0) | |
c44b31c2 | 245 | return false; |
bc3665fd CL |
246 | p = xdr_inline_decode(xdr, SM_PRIV_SIZE); |
247 | if (!p) | |
c44b31c2 | 248 | return false; |
bc3665fd CL |
249 | memcpy(&argp->priv.data, p, sizeof(argp->priv.data)); |
250 | ||
c44b31c2 | 251 | return true; |
bc3665fd CL |
252 | } |
253 | ||
c44b31c2 | 254 | bool |
16c66364 | 255 | nlm4svc_decode_shareargs(struct svc_rqst *rqstp, struct xdr_stream *xdr) |
1da177e4 | 256 | { |
026fec7e | 257 | struct nlm_args *argp = rqstp->rq_argp; |
1da177e4 LT |
258 | struct nlm_lock *lock = &argp->lock; |
259 | ||
260 | memset(lock, 0, sizeof(*lock)); | |
261 | locks_init_lock(&lock->fl); | |
7cf96b6d | 262 | lock->svid = ~(u32)0; |
1da177e4 | 263 | |
7cf96b6d | 264 | if (!svcxdr_decode_cookie(xdr, &argp->cookie)) |
c44b31c2 | 265 | return false; |
7cf96b6d | 266 | if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len)) |
c44b31c2 | 267 | return false; |
7cf96b6d | 268 | if (!svcxdr_decode_fhandle(xdr, &lock->fh)) |
c44b31c2 | 269 | return false; |
7cf96b6d | 270 | if (!svcxdr_decode_owner(xdr, &lock->oh)) |
c44b31c2 | 271 | return false; |
7cf96b6d CL |
272 | /* XXX: Range checks are missing in the original code */ |
273 | if (xdr_stream_decode_u32(xdr, &argp->fsm_mode) < 0) | |
c44b31c2 | 274 | return false; |
7cf96b6d | 275 | if (xdr_stream_decode_u32(xdr, &argp->fsm_access) < 0) |
c44b31c2 | 276 | return false; |
7cf96b6d | 277 | |
c44b31c2 | 278 | return true; |
7cf96b6d CL |
279 | } |
280 | ||
c44b31c2 | 281 | bool |
16c66364 | 282 | nlm4svc_decode_notify(struct svc_rqst *rqstp, struct xdr_stream *xdr) |
3049e974 | 283 | { |
3049e974 CL |
284 | struct nlm_args *argp = rqstp->rq_argp; |
285 | struct nlm_lock *lock = &argp->lock; | |
286 | ||
287 | if (!svcxdr_decode_string(xdr, &lock->caller, &lock->len)) | |
c44b31c2 | 288 | return false; |
3049e974 | 289 | if (xdr_stream_decode_u32(xdr, &argp->state) < 0) |
c44b31c2 | 290 | return false; |
3049e974 | 291 | |
c44b31c2 | 292 | return true; |
3049e974 CL |
293 | } |
294 | ||
ec757e42 CL |
295 | |
296 | /* | |
297 | * Encode Reply results | |
298 | */ | |
299 | ||
130e2054 | 300 | bool |
fda49441 | 301 | nlm4svc_encode_void(struct svc_rqst *rqstp, struct xdr_stream *xdr) |
ec757e42 | 302 | { |
130e2054 | 303 | return true; |
ec757e42 CL |
304 | } |
305 | ||
130e2054 | 306 | bool |
fda49441 | 307 | nlm4svc_encode_testres(struct svc_rqst *rqstp, struct xdr_stream *xdr) |
7cf96b6d CL |
308 | { |
309 | struct nlm_res *resp = rqstp->rq_resp; | |
310 | ||
1beef147 CL |
311 | return svcxdr_encode_cookie(xdr, &resp->cookie) && |
312 | svcxdr_encode_testrply(xdr, resp); | |
1da177e4 LT |
313 | } |
314 | ||
130e2054 | 315 | bool |
fda49441 | 316 | nlm4svc_encode_res(struct svc_rqst *rqstp, struct xdr_stream *xdr) |
1da177e4 | 317 | { |
63f8de37 CH |
318 | struct nlm_res *resp = rqstp->rq_resp; |
319 | ||
447c14d4 CL |
320 | return svcxdr_encode_cookie(xdr, &resp->cookie) && |
321 | svcxdr_encode_stats(xdr, resp->status); | |
1da177e4 LT |
322 | } |
323 | ||
130e2054 | 324 | bool |
fda49441 | 325 | nlm4svc_encode_shareres(struct svc_rqst *rqstp, struct xdr_stream *xdr) |
1da177e4 | 326 | { |
63f8de37 CH |
327 | struct nlm_res *resp = rqstp->rq_resp; |
328 | ||
0ff5b50a | 329 | if (!svcxdr_encode_cookie(xdr, &resp->cookie)) |
130e2054 | 330 | return false; |
0ff5b50a | 331 | if (!svcxdr_encode_stats(xdr, resp->status)) |
130e2054 | 332 | return false; |
0ff5b50a CL |
333 | /* sequence */ |
334 | if (xdr_stream_encode_u32(xdr, 0) < 0) | |
130e2054 | 335 | return false; |
0ff5b50a | 336 | |
130e2054 | 337 | return true; |
1da177e4 | 338 | } |