aboutsummaryrefslogtreecommitdiffstats
path: root/fs/lockd/mon.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2008-12-05 19:02:15 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-01-06 11:53:53 -0500
commit03eb1dcbb799304b58730f4dba65812f49fb305e (patch)
tree310306a570ae554fd420bdde1fdabe7f1157c255 /fs/lockd/mon.c
parent36e8e668d3e6a61848a8921ddeb663b417299fa5 (diff)
NSM: move to xdr_stream-based XDR encoders and decoders
Introduce xdr_stream-based XDR encoder and decoder functions, which are more careful about preventing RPC buffer overflows. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs/lockd/mon.c')
-rw-r--r--fs/lockd/mon.c130
1 files changed, 78 insertions, 52 deletions
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 0fc9836db4e7..81e1cc14246f 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -193,21 +193,26 @@ nsm_create(void)
193 * Status Monitor wire protocol. 193 * Status Monitor wire protocol.
194 */ 194 */
195 195
196static __be32 *xdr_encode_nsm_string(__be32 *p, char *string) 196static int encode_nsm_string(struct xdr_stream *xdr, const char *string)
197{ 197{
198 size_t len = strlen(string); 198 const u32 len = strlen(string);
199 199 __be32 *p;
200 if (len > SM_MAXSTRLEN) 200
201 len = SM_MAXSTRLEN; 201 if (unlikely(len > SM_MAXSTRLEN))
202 return xdr_encode_opaque(p, string, len); 202 return -EIO;
203 p = xdr_reserve_space(xdr, sizeof(u32) + len);
204 if (unlikely(p == NULL))
205 return -EIO;
206 xdr_encode_opaque(p, string, len);
207 return 0;
203} 208}
204 209
205/* 210/*
206 * "mon_name" specifies the host to be monitored. 211 * "mon_name" specifies the host to be monitored.
207 */ 212 */
208static __be32 *xdr_encode_mon_name(__be32 *p, struct nsm_args *argp) 213static int encode_mon_name(struct xdr_stream *xdr, const struct nsm_args *argp)
209{ 214{
210 return xdr_encode_nsm_string(p, argp->mon_name); 215 return encode_nsm_string(xdr, argp->mon_name);
211} 216}
212 217
213/* 218/*
@@ -216,30 +221,35 @@ static __be32 *xdr_encode_mon_name(__be32 *p, struct nsm_args *argp)
216 * (via the NLMPROC_SM_NOTIFY call) that the state of host "mon_name" 221 * (via the NLMPROC_SM_NOTIFY call) that the state of host "mon_name"
217 * has changed. 222 * has changed.
218 */ 223 */
219static __be32 *xdr_encode_my_id(__be32 *p, struct nsm_args *argp) 224static int encode_my_id(struct xdr_stream *xdr, const struct nsm_args *argp)
220{ 225{
221 p = xdr_encode_nsm_string(p, utsname()->nodename); 226 int status;
222 if (!p) 227 __be32 *p;
223 return ERR_PTR(-EIO); 228
224 229 status = encode_nsm_string(xdr, utsname()->nodename);
230 if (unlikely(status != 0))
231 return status;
232 p = xdr_reserve_space(xdr, 3 * sizeof(u32));
233 if (unlikely(p == NULL))
234 return -EIO;
225 *p++ = htonl(argp->prog); 235 *p++ = htonl(argp->prog);
226 *p++ = htonl(argp->vers); 236 *p++ = htonl(argp->vers);
227 *p++ = htonl(argp->proc); 237 *p++ = htonl(argp->proc);
228 238 return 0;
229 return p;
230} 239}
231 240
232/* 241/*
233 * The "mon_id" argument specifies the non-private arguments 242 * The "mon_id" argument specifies the non-private arguments
234 * of an NSMPROC_MON or NSMPROC_UNMON call. 243 * of an NSMPROC_MON or NSMPROC_UNMON call.
235 */ 244 */
236static __be32 *xdr_encode_mon_id(__be32 *p, struct nsm_args *argp) 245static int encode_mon_id(struct xdr_stream *xdr, const struct nsm_args *argp)
237{ 246{
238 p = xdr_encode_mon_name(p, argp); 247 int status;
239 if (!p)
240 return ERR_PTR(-EIO);
241 248
242 return xdr_encode_my_id(p, argp); 249 status = encode_mon_name(xdr, argp);
250 if (unlikely(status != 0))
251 return status;
252 return encode_my_id(xdr, argp);
243} 253}
244 254
245/* 255/*
@@ -250,55 +260,71 @@ static __be32 *xdr_encode_mon_id(__be32 *p, struct nsm_args *argp)
250 * Linux provides the raw IP address of the monitored host, 260 * Linux provides the raw IP address of the monitored host,
251 * left in network byte order. 261 * left in network byte order.
252 */ 262 */
253static __be32 *xdr_encode_priv(__be32 *p, struct nsm_args *argp) 263static int encode_priv(struct xdr_stream *xdr, const struct nsm_args *argp)
254{ 264{
265 __be32 *p;
266
267 p = xdr_reserve_space(xdr, SM_PRIV_SIZE);
268 if (unlikely(p == NULL))
269 return -EIO;
255 *p++ = argp->addr; 270 *p++ = argp->addr;
256 *p++ = 0; 271 *p++ = 0;
257 *p++ = 0; 272 *p++ = 0;
258 *p++ = 0; 273 *p++ = 0;
259 274 return 0;
260 return p;
261} 275}
262 276
263static int 277static int xdr_enc_mon(struct rpc_rqst *req, __be32 *p,
264xdr_encode_mon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) 278 const struct nsm_args *argp)
265{ 279{
266 p = xdr_encode_mon_id(p, argp); 280 struct xdr_stream xdr;
267 if (IS_ERR(p)) 281 int status;
268 return PTR_ERR(p);
269
270 p = xdr_encode_priv(p, argp);
271 if (IS_ERR(p))
272 return PTR_ERR(p);
273 282
274 rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); 283 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
275 return 0; 284 status = encode_mon_id(&xdr, argp);
285 if (unlikely(status))
286 return status;
287 return encode_priv(&xdr, argp);
276} 288}
277 289
278static int 290static int xdr_enc_unmon(struct rpc_rqst *req, __be32 *p,
279xdr_encode_unmon(struct rpc_rqst *rqstp, __be32 *p, struct nsm_args *argp) 291 const struct nsm_args *argp)
280{ 292{
281 p = xdr_encode_mon_id(p, argp); 293 struct xdr_stream xdr;
282 if (IS_ERR(p)) 294
283 return PTR_ERR(p); 295 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
284 rqstp->rq_slen = xdr_adjust_iovec(rqstp->rq_svec, p); 296 return encode_mon_id(&xdr, argp);
285 return 0;
286} 297}
287 298
288static int 299static int xdr_dec_stat_res(struct rpc_rqst *rqstp, __be32 *p,
289xdr_decode_stat_res(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp) 300 struct nsm_res *resp)
290{ 301{
302 struct xdr_stream xdr;
303
304 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
305 p = xdr_inline_decode(&xdr, 2 * sizeof(u32));
306 if (unlikely(p == NULL))
307 return -EIO;
291 resp->status = ntohl(*p++); 308 resp->status = ntohl(*p++);
292 resp->state = ntohl(*p++); 309 resp->state = ntohl(*p);
293 dprintk("nsm: xdr_decode_stat_res status %d state %d\n", 310
311 dprintk("lockd: xdr_dec_stat_res status %d state %d\n",
294 resp->status, resp->state); 312 resp->status, resp->state);
295 return 0; 313 return 0;
296} 314}
297 315
298static int 316static int xdr_dec_stat(struct rpc_rqst *rqstp, __be32 *p,
299xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp) 317 struct nsm_res *resp)
300{ 318{
301 resp->state = ntohl(*p++); 319 struct xdr_stream xdr;
320
321 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
322 p = xdr_inline_decode(&xdr, sizeof(u32));
323 if (unlikely(p == NULL))
324 return -EIO;
325 resp->state = ntohl(*p);
326
327 dprintk("lockd: xdr_dec_stat state %d\n", resp->state);
302 return 0; 328 return 0;
303} 329}
304 330
@@ -314,8 +340,8 @@ xdr_decode_stat(struct rpc_rqst *rqstp, __be32 *p, struct nsm_res *resp)
314static struct rpc_procinfo nsm_procedures[] = { 340static struct rpc_procinfo nsm_procedures[] = {
315[NSMPROC_MON] = { 341[NSMPROC_MON] = {
316 .p_proc = NSMPROC_MON, 342 .p_proc = NSMPROC_MON,
317 .p_encode = (kxdrproc_t) xdr_encode_mon, 343 .p_encode = (kxdrproc_t)xdr_enc_mon,
318 .p_decode = (kxdrproc_t) xdr_decode_stat_res, 344 .p_decode = (kxdrproc_t)xdr_dec_stat_res,
319 .p_arglen = SM_mon_sz, 345 .p_arglen = SM_mon_sz,
320 .p_replen = SM_monres_sz, 346 .p_replen = SM_monres_sz,
321 .p_statidx = NSMPROC_MON, 347 .p_statidx = NSMPROC_MON,
@@ -323,8 +349,8 @@ static struct rpc_procinfo nsm_procedures[] = {
323 }, 349 },
324[NSMPROC_UNMON] = { 350[NSMPROC_UNMON] = {
325 .p_proc = NSMPROC_UNMON, 351 .p_proc = NSMPROC_UNMON,
326 .p_encode = (kxdrproc_t) xdr_encode_unmon, 352 .p_encode = (kxdrproc_t)xdr_enc_unmon,
327 .p_decode = (kxdrproc_t) xdr_decode_stat, 353 .p_decode = (kxdrproc_t)xdr_dec_stat,
328 .p_arglen = SM_mon_id_sz, 354 .p_arglen = SM_mon_id_sz,
329 .p_replen = SM_unmonres_sz, 355 .p_replen = SM_unmonres_sz,
330 .p_statidx = NSMPROC_UNMON, 356 .p_statidx = NSMPROC_UNMON,