diff options
-rw-r--r-- | fs/exec.c | 8 | ||||
-rw-r--r-- | fs/lockd/svcsubs.c | 15 | ||||
-rw-r--r-- | fs/namei.c | 11 | ||||
-rw-r--r-- | fs/nfs/file.c | 8 | ||||
-rw-r--r-- | fs/nfs/idmap.c | 4 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 29 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 21 | ||||
-rw-r--r-- | fs/nfs/read.c | 23 | ||||
-rw-r--r-- | include/linux/nfs_xdr.h | 2 | ||||
-rw-r--r-- | include/linux/sunrpc/rpc_pipe_fs.h | 4 | ||||
-rw-r--r-- | include/linux/sunrpc/xprt.h | 2 | ||||
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 3 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 30 | ||||
-rw-r--r-- | net/sunrpc/rpc_pipe.c | 55 |
14 files changed, 125 insertions, 90 deletions
@@ -486,8 +486,6 @@ struct file *open_exec(const char *name) | |||
486 | if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && | 486 | if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && |
487 | S_ISREG(inode->i_mode)) { | 487 | S_ISREG(inode->i_mode)) { |
488 | int err = vfs_permission(&nd, MAY_EXEC); | 488 | int err = vfs_permission(&nd, MAY_EXEC); |
489 | if (!err && !(inode->i_mode & 0111)) | ||
490 | err = -EACCES; | ||
491 | file = ERR_PTR(err); | 489 | file = ERR_PTR(err); |
492 | if (!err) { | 490 | if (!err) { |
493 | file = nameidata_to_filp(&nd, O_RDONLY); | 491 | file = nameidata_to_filp(&nd, O_RDONLY); |
@@ -922,12 +920,6 @@ int prepare_binprm(struct linux_binprm *bprm) | |||
922 | int retval; | 920 | int retval; |
923 | 921 | ||
924 | mode = inode->i_mode; | 922 | mode = inode->i_mode; |
925 | /* | ||
926 | * Check execute perms again - if the caller has CAP_DAC_OVERRIDE, | ||
927 | * generic_permission lets a non-executable through | ||
928 | */ | ||
929 | if (!(mode & 0111)) /* with at least _one_ execute bit set */ | ||
930 | return -EACCES; | ||
931 | if (bprm->file->f_op == NULL) | 923 | if (bprm->file->f_op == NULL) |
932 | return -EACCES; | 924 | return -EACCES; |
933 | 925 | ||
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 2a4df9b3779a..01b4db9e5466 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c | |||
@@ -237,19 +237,22 @@ static int | |||
237 | nlm_traverse_files(struct nlm_host *host, int action) | 237 | nlm_traverse_files(struct nlm_host *host, int action) |
238 | { | 238 | { |
239 | struct nlm_file *file, **fp; | 239 | struct nlm_file *file, **fp; |
240 | int i; | 240 | int i, ret = 0; |
241 | 241 | ||
242 | mutex_lock(&nlm_file_mutex); | 242 | mutex_lock(&nlm_file_mutex); |
243 | for (i = 0; i < FILE_NRHASH; i++) { | 243 | for (i = 0; i < FILE_NRHASH; i++) { |
244 | fp = nlm_files + i; | 244 | fp = nlm_files + i; |
245 | while ((file = *fp) != NULL) { | 245 | while ((file = *fp) != NULL) { |
246 | file->f_count++; | ||
247 | mutex_unlock(&nlm_file_mutex); | ||
248 | |||
246 | /* Traverse locks, blocks and shares of this file | 249 | /* Traverse locks, blocks and shares of this file |
247 | * and update file->f_locks count */ | 250 | * and update file->f_locks count */ |
248 | if (nlm_inspect_file(host, file, action)) { | 251 | if (nlm_inspect_file(host, file, action)) |
249 | mutex_unlock(&nlm_file_mutex); | 252 | ret = 1; |
250 | return 1; | ||
251 | } | ||
252 | 253 | ||
254 | mutex_lock(&nlm_file_mutex); | ||
255 | file->f_count--; | ||
253 | /* No more references to this file. Let go of it. */ | 256 | /* No more references to this file. Let go of it. */ |
254 | if (!file->f_blocks && !file->f_locks | 257 | if (!file->f_blocks && !file->f_locks |
255 | && !file->f_shares && !file->f_count) { | 258 | && !file->f_shares && !file->f_count) { |
@@ -262,7 +265,7 @@ nlm_traverse_files(struct nlm_host *host, int action) | |||
262 | } | 265 | } |
263 | } | 266 | } |
264 | mutex_unlock(&nlm_file_mutex); | 267 | mutex_unlock(&nlm_file_mutex); |
265 | return 0; | 268 | return ret; |
266 | } | 269 | } |
267 | 270 | ||
268 | /* | 271 | /* |
diff --git a/fs/namei.c b/fs/namei.c index 55a131230f94..432d6bc6fab0 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -227,10 +227,10 @@ int generic_permission(struct inode *inode, int mask, | |||
227 | 227 | ||
228 | int permission(struct inode *inode, int mask, struct nameidata *nd) | 228 | int permission(struct inode *inode, int mask, struct nameidata *nd) |
229 | { | 229 | { |
230 | umode_t mode = inode->i_mode; | ||
230 | int retval, submask; | 231 | int retval, submask; |
231 | 232 | ||
232 | if (mask & MAY_WRITE) { | 233 | if (mask & MAY_WRITE) { |
233 | umode_t mode = inode->i_mode; | ||
234 | 234 | ||
235 | /* | 235 | /* |
236 | * Nobody gets write access to a read-only fs. | 236 | * Nobody gets write access to a read-only fs. |
@@ -247,6 +247,13 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) | |||
247 | } | 247 | } |
248 | 248 | ||
249 | 249 | ||
250 | /* | ||
251 | * MAY_EXEC on regular files requires special handling: We override | ||
252 | * filesystem execute permissions if the mode bits aren't set. | ||
253 | */ | ||
254 | if ((mask & MAY_EXEC) && S_ISREG(mode) && !(mode & S_IXUGO)) | ||
255 | return -EACCES; | ||
256 | |||
250 | /* Ordinary permission routines do not understand MAY_APPEND. */ | 257 | /* Ordinary permission routines do not understand MAY_APPEND. */ |
251 | submask = mask & ~MAY_APPEND; | 258 | submask = mask & ~MAY_APPEND; |
252 | if (inode->i_op && inode->i_op->permission) | 259 | if (inode->i_op && inode->i_op->permission) |
@@ -1767,6 +1774,8 @@ struct dentry *lookup_create(struct nameidata *nd, int is_dir) | |||
1767 | if (nd->last_type != LAST_NORM) | 1774 | if (nd->last_type != LAST_NORM) |
1768 | goto fail; | 1775 | goto fail; |
1769 | nd->flags &= ~LOOKUP_PARENT; | 1776 | nd->flags &= ~LOOKUP_PARENT; |
1777 | nd->flags |= LOOKUP_CREATE; | ||
1778 | nd->intent.open.flags = O_EXCL; | ||
1770 | 1779 | ||
1771 | /* | 1780 | /* |
1772 | * Do the final lookup. | 1781 | * Do the final lookup. |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index cc2b874ad5a4..48e892880d5b 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -312,7 +312,13 @@ static void nfs_invalidate_page(struct page *page, unsigned long offset) | |||
312 | 312 | ||
313 | static int nfs_release_page(struct page *page, gfp_t gfp) | 313 | static int nfs_release_page(struct page *page, gfp_t gfp) |
314 | { | 314 | { |
315 | return !nfs_wb_page(page->mapping->host, page); | 315 | if (gfp & __GFP_FS) |
316 | return !nfs_wb_page(page->mapping->host, page); | ||
317 | else | ||
318 | /* | ||
319 | * Avoid deadlock on nfs_wait_on_request(). | ||
320 | */ | ||
321 | return 0; | ||
316 | } | 322 | } |
317 | 323 | ||
318 | const struct address_space_operations nfs_file_aops = { | 324 | const struct address_space_operations nfs_file_aops = { |
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index b81e7ed3c902..07a5dd57646e 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -130,9 +130,7 @@ nfs_idmap_delete(struct nfs4_client *clp) | |||
130 | 130 | ||
131 | if (!idmap) | 131 | if (!idmap) |
132 | return; | 132 | return; |
133 | dput(idmap->idmap_dentry); | 133 | rpc_unlink(idmap->idmap_dentry); |
134 | idmap->idmap_dentry = NULL; | ||
135 | rpc_unlink(idmap->idmap_path); | ||
136 | clp->cl_idmap = NULL; | 134 | clp->cl_idmap = NULL; |
137 | kfree(idmap); | 135 | kfree(idmap); |
138 | } | 136 | } |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e6ee97f19d81..153898e1331f 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -2668,7 +2668,7 @@ out: | |||
2668 | nfs4_set_cached_acl(inode, acl); | 2668 | nfs4_set_cached_acl(inode, acl); |
2669 | } | 2669 | } |
2670 | 2670 | ||
2671 | static inline ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen) | 2671 | static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen) |
2672 | { | 2672 | { |
2673 | struct page *pages[NFS4ACL_MAXPAGES]; | 2673 | struct page *pages[NFS4ACL_MAXPAGES]; |
2674 | struct nfs_getaclargs args = { | 2674 | struct nfs_getaclargs args = { |
@@ -2721,6 +2721,19 @@ out_free: | |||
2721 | return ret; | 2721 | return ret; |
2722 | } | 2722 | } |
2723 | 2723 | ||
2724 | static ssize_t nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t buflen) | ||
2725 | { | ||
2726 | struct nfs4_exception exception = { }; | ||
2727 | ssize_t ret; | ||
2728 | do { | ||
2729 | ret = __nfs4_get_acl_uncached(inode, buf, buflen); | ||
2730 | if (ret >= 0) | ||
2731 | break; | ||
2732 | ret = nfs4_handle_exception(NFS_SERVER(inode), ret, &exception); | ||
2733 | } while (exception.retry); | ||
2734 | return ret; | ||
2735 | } | ||
2736 | |||
2724 | static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) | 2737 | static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) |
2725 | { | 2738 | { |
2726 | struct nfs_server *server = NFS_SERVER(inode); | 2739 | struct nfs_server *server = NFS_SERVER(inode); |
@@ -2737,7 +2750,7 @@ static ssize_t nfs4_proc_get_acl(struct inode *inode, void *buf, size_t buflen) | |||
2737 | return nfs4_get_acl_uncached(inode, buf, buflen); | 2750 | return nfs4_get_acl_uncached(inode, buf, buflen); |
2738 | } | 2751 | } |
2739 | 2752 | ||
2740 | static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen) | 2753 | static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen) |
2741 | { | 2754 | { |
2742 | struct nfs_server *server = NFS_SERVER(inode); | 2755 | struct nfs_server *server = NFS_SERVER(inode); |
2743 | struct page *pages[NFS4ACL_MAXPAGES]; | 2756 | struct page *pages[NFS4ACL_MAXPAGES]; |
@@ -2763,6 +2776,18 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
2763 | return ret; | 2776 | return ret; |
2764 | } | 2777 | } |
2765 | 2778 | ||
2779 | static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen) | ||
2780 | { | ||
2781 | struct nfs4_exception exception = { }; | ||
2782 | int err; | ||
2783 | do { | ||
2784 | err = nfs4_handle_exception(NFS_SERVER(inode), | ||
2785 | __nfs4_proc_set_acl(inode, buf, buflen), | ||
2786 | &exception); | ||
2787 | } while (exception.retry); | ||
2788 | return err; | ||
2789 | } | ||
2790 | |||
2766 | static int | 2791 | static int |
2767 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) | 2792 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server) |
2768 | { | 2793 | { |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 1750d996f49f..730ec8fb31c6 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -3355,7 +3355,7 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
3355 | struct kvec *iov = rcvbuf->head; | 3355 | struct kvec *iov = rcvbuf->head; |
3356 | unsigned int nr, pglen = rcvbuf->page_len; | 3356 | unsigned int nr, pglen = rcvbuf->page_len; |
3357 | uint32_t *end, *entry, *p, *kaddr; | 3357 | uint32_t *end, *entry, *p, *kaddr; |
3358 | uint32_t len, attrlen; | 3358 | uint32_t len, attrlen, xlen; |
3359 | int hdrlen, recvd, status; | 3359 | int hdrlen, recvd, status; |
3360 | 3360 | ||
3361 | status = decode_op_hdr(xdr, OP_READDIR); | 3361 | status = decode_op_hdr(xdr, OP_READDIR); |
@@ -3377,10 +3377,10 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
3377 | 3377 | ||
3378 | BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE); | 3378 | BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE); |
3379 | kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0); | 3379 | kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0); |
3380 | end = (uint32_t *) ((char *)p + pglen + readdir->pgbase); | 3380 | end = p + ((pglen + readdir->pgbase) >> 2); |
3381 | entry = p; | 3381 | entry = p; |
3382 | for (nr = 0; *p++; nr++) { | 3382 | for (nr = 0; *p++; nr++) { |
3383 | if (p + 3 > end) | 3383 | if (end - p < 3) |
3384 | goto short_pkt; | 3384 | goto short_pkt; |
3385 | dprintk("cookie = %Lu, ", *((unsigned long long *)p)); | 3385 | dprintk("cookie = %Lu, ", *((unsigned long long *)p)); |
3386 | p += 2; /* cookie */ | 3386 | p += 2; /* cookie */ |
@@ -3389,18 +3389,19 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n | |||
3389 | printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len); | 3389 | printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len); |
3390 | goto err_unmap; | 3390 | goto err_unmap; |
3391 | } | 3391 | } |
3392 | dprintk("filename = %*s\n", len, (char *)p); | 3392 | xlen = XDR_QUADLEN(len); |
3393 | p += XDR_QUADLEN(len); | 3393 | if (end - p < xlen + 1) |
3394 | if (p + 1 > end) | ||
3395 | goto short_pkt; | 3394 | goto short_pkt; |
3395 | dprintk("filename = %*s\n", len, (char *)p); | ||
3396 | p += xlen; | ||
3396 | len = ntohl(*p++); /* bitmap length */ | 3397 | len = ntohl(*p++); /* bitmap length */ |
3397 | p += len; | 3398 | if (end - p < len + 1) |
3398 | if (p + 1 > end) | ||
3399 | goto short_pkt; | 3399 | goto short_pkt; |
3400 | p += len; | ||
3400 | attrlen = XDR_QUADLEN(ntohl(*p++)); | 3401 | attrlen = XDR_QUADLEN(ntohl(*p++)); |
3401 | p += attrlen; /* attributes */ | 3402 | if (end - p < attrlen + 2) |
3402 | if (p + 2 > end) | ||
3403 | goto short_pkt; | 3403 | goto short_pkt; |
3404 | p += attrlen; /* attributes */ | ||
3404 | entry = p; | 3405 | entry = p; |
3405 | } | 3406 | } |
3406 | if (!nr && (entry[0] != 0 || entry[1] == 0)) | 3407 | if (!nr && (entry[0] != 0 || entry[1] == 0)) |
diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 65c0c5b32351..da9cf11c326f 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c | |||
@@ -116,10 +116,17 @@ static void nfs_readpage_truncate_uninitialised_page(struct nfs_read_data *data) | |||
116 | pages = &data->args.pages[base >> PAGE_CACHE_SHIFT]; | 116 | pages = &data->args.pages[base >> PAGE_CACHE_SHIFT]; |
117 | base &= ~PAGE_CACHE_MASK; | 117 | base &= ~PAGE_CACHE_MASK; |
118 | pglen = PAGE_CACHE_SIZE - base; | 118 | pglen = PAGE_CACHE_SIZE - base; |
119 | if (pglen < remainder) | 119 | for (;;) { |
120 | if (remainder <= pglen) { | ||
121 | memclear_highpage_flush(*pages, base, remainder); | ||
122 | break; | ||
123 | } | ||
120 | memclear_highpage_flush(*pages, base, pglen); | 124 | memclear_highpage_flush(*pages, base, pglen); |
121 | else | 125 | pages++; |
122 | memclear_highpage_flush(*pages, base, remainder); | 126 | remainder -= pglen; |
127 | pglen = PAGE_CACHE_SIZE; | ||
128 | base = 0; | ||
129 | } | ||
123 | } | 130 | } |
124 | 131 | ||
125 | /* | 132 | /* |
@@ -476,6 +483,8 @@ static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data) | |||
476 | unsigned int base = data->args.pgbase; | 483 | unsigned int base = data->args.pgbase; |
477 | struct page **pages; | 484 | struct page **pages; |
478 | 485 | ||
486 | if (data->res.eof) | ||
487 | count = data->args.count; | ||
479 | if (unlikely(count == 0)) | 488 | if (unlikely(count == 0)) |
480 | return; | 489 | return; |
481 | pages = &data->args.pages[base >> PAGE_CACHE_SHIFT]; | 490 | pages = &data->args.pages[base >> PAGE_CACHE_SHIFT]; |
@@ -483,11 +492,7 @@ static void nfs_readpage_set_pages_uptodate(struct nfs_read_data *data) | |||
483 | count += base; | 492 | count += base; |
484 | for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++) | 493 | for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++) |
485 | SetPageUptodate(*pages); | 494 | SetPageUptodate(*pages); |
486 | /* | 495 | if (count != 0) |
487 | * Was this an eof or a short read? If the latter, don't mark the page | ||
488 | * as uptodate yet. | ||
489 | */ | ||
490 | if (count > 0 && (data->res.eof || data->args.count == data->res.count)) | ||
491 | SetPageUptodate(*pages); | 496 | SetPageUptodate(*pages); |
492 | } | 497 | } |
493 | 498 | ||
@@ -502,6 +507,8 @@ static void nfs_readpage_set_pages_error(struct nfs_read_data *data) | |||
502 | count += base; | 507 | count += base; |
503 | for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++) | 508 | for (;count >= PAGE_CACHE_SIZE; count -= PAGE_CACHE_SIZE, pages++) |
504 | SetPageError(*pages); | 509 | SetPageError(*pages); |
510 | if (count != 0) | ||
511 | SetPageError(*pages); | ||
505 | } | 512 | } |
506 | 513 | ||
507 | /* | 514 | /* |
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h index 2d3fb6416d91..db9cbf68e12b 100644 --- a/include/linux/nfs_xdr.h +++ b/include/linux/nfs_xdr.h | |||
@@ -659,7 +659,7 @@ struct nfs4_rename_res { | |||
659 | struct nfs4_setclientid { | 659 | struct nfs4_setclientid { |
660 | const nfs4_verifier * sc_verifier; /* request */ | 660 | const nfs4_verifier * sc_verifier; /* request */ |
661 | unsigned int sc_name_len; | 661 | unsigned int sc_name_len; |
662 | char sc_name[32]; /* request */ | 662 | char sc_name[48]; /* request */ |
663 | u32 sc_prog; /* request */ | 663 | u32 sc_prog; /* request */ |
664 | unsigned int sc_netid_len; | 664 | unsigned int sc_netid_len; |
665 | char sc_netid[4]; /* request */ | 665 | char sc_netid[4]; /* request */ |
diff --git a/include/linux/sunrpc/rpc_pipe_fs.h b/include/linux/sunrpc/rpc_pipe_fs.h index 2c2189cb30aa..a481472c9484 100644 --- a/include/linux/sunrpc/rpc_pipe_fs.h +++ b/include/linux/sunrpc/rpc_pipe_fs.h | |||
@@ -42,9 +42,9 @@ RPC_I(struct inode *inode) | |||
42 | extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *); | 42 | extern int rpc_queue_upcall(struct inode *, struct rpc_pipe_msg *); |
43 | 43 | ||
44 | extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *); | 44 | extern struct dentry *rpc_mkdir(char *, struct rpc_clnt *); |
45 | extern int rpc_rmdir(char *); | 45 | extern int rpc_rmdir(struct dentry *); |
46 | extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags); | 46 | extern struct dentry *rpc_mkpipe(char *, void *, struct rpc_pipe_ops *, int flags); |
47 | extern int rpc_unlink(char *); | 47 | extern int rpc_unlink(struct dentry *); |
48 | extern struct vfsmount *rpc_get_mount(void); | 48 | extern struct vfsmount *rpc_get_mount(void); |
49 | extern void rpc_put_mount(void); | 49 | extern void rpc_put_mount(void); |
50 | 50 | ||
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index 840e47a4ccc5..3a0cca255b76 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
@@ -37,7 +37,7 @@ extern unsigned int xprt_max_resvport; | |||
37 | 37 | ||
38 | #define RPC_MIN_RESVPORT (1U) | 38 | #define RPC_MIN_RESVPORT (1U) |
39 | #define RPC_MAX_RESVPORT (65535U) | 39 | #define RPC_MAX_RESVPORT (65535U) |
40 | #define RPC_DEF_MIN_RESVPORT (650U) | 40 | #define RPC_DEF_MIN_RESVPORT (665U) |
41 | #define RPC_DEF_MAX_RESVPORT (1023U) | 41 | #define RPC_DEF_MAX_RESVPORT (1023U) |
42 | 42 | ||
43 | /* | 43 | /* |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index 4a9aa9393b97..ef1cf5b476c8 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -718,8 +718,7 @@ gss_destroy(struct rpc_auth *auth) | |||
718 | auth, auth->au_flavor); | 718 | auth, auth->au_flavor); |
719 | 719 | ||
720 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); | 720 | gss_auth = container_of(auth, struct gss_auth, rpc_auth); |
721 | rpc_unlink(gss_auth->path); | 721 | rpc_unlink(gss_auth->dentry); |
722 | dput(gss_auth->dentry); | ||
723 | gss_auth->dentry = NULL; | 722 | gss_auth->dentry = NULL; |
724 | gss_mech_put(gss_auth->mech); | 723 | gss_mech_put(gss_auth->mech); |
725 | 724 | ||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index d6409e757219..3e19d321067a 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -183,8 +183,7 @@ rpc_new_client(struct rpc_xprt *xprt, char *servname, | |||
183 | 183 | ||
184 | out_no_auth: | 184 | out_no_auth: |
185 | if (!IS_ERR(clnt->cl_dentry)) { | 185 | if (!IS_ERR(clnt->cl_dentry)) { |
186 | rpc_rmdir(clnt->cl_pathname); | 186 | rpc_rmdir(clnt->cl_dentry); |
187 | dput(clnt->cl_dentry); | ||
188 | rpc_put_mount(); | 187 | rpc_put_mount(); |
189 | } | 188 | } |
190 | out_no_path: | 189 | out_no_path: |
@@ -251,10 +250,8 @@ rpc_clone_client(struct rpc_clnt *clnt) | |||
251 | new->cl_autobind = 0; | 250 | new->cl_autobind = 0; |
252 | new->cl_oneshot = 0; | 251 | new->cl_oneshot = 0; |
253 | new->cl_dead = 0; | 252 | new->cl_dead = 0; |
254 | if (!IS_ERR(new->cl_dentry)) { | 253 | if (!IS_ERR(new->cl_dentry)) |
255 | dget(new->cl_dentry); | 254 | dget(new->cl_dentry); |
256 | rpc_get_mount(); | ||
257 | } | ||
258 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); | 255 | rpc_init_rtt(&new->cl_rtt_default, clnt->cl_xprt->timeout.to_initval); |
259 | if (new->cl_auth) | 256 | if (new->cl_auth) |
260 | atomic_inc(&new->cl_auth->au_count); | 257 | atomic_inc(&new->cl_auth->au_count); |
@@ -317,11 +314,15 @@ rpc_destroy_client(struct rpc_clnt *clnt) | |||
317 | clnt->cl_auth = NULL; | 314 | clnt->cl_auth = NULL; |
318 | } | 315 | } |
319 | if (clnt->cl_parent != clnt) { | 316 | if (clnt->cl_parent != clnt) { |
317 | if (!IS_ERR(clnt->cl_dentry)) | ||
318 | dput(clnt->cl_dentry); | ||
320 | rpc_destroy_client(clnt->cl_parent); | 319 | rpc_destroy_client(clnt->cl_parent); |
321 | goto out_free; | 320 | goto out_free; |
322 | } | 321 | } |
323 | if (clnt->cl_pathname[0]) | 322 | if (!IS_ERR(clnt->cl_dentry)) { |
324 | rpc_rmdir(clnt->cl_pathname); | 323 | rpc_rmdir(clnt->cl_dentry); |
324 | rpc_put_mount(); | ||
325 | } | ||
325 | if (clnt->cl_xprt) { | 326 | if (clnt->cl_xprt) { |
326 | xprt_destroy(clnt->cl_xprt); | 327 | xprt_destroy(clnt->cl_xprt); |
327 | clnt->cl_xprt = NULL; | 328 | clnt->cl_xprt = NULL; |
@@ -331,10 +332,6 @@ rpc_destroy_client(struct rpc_clnt *clnt) | |||
331 | out_free: | 332 | out_free: |
332 | rpc_free_iostats(clnt->cl_metrics); | 333 | rpc_free_iostats(clnt->cl_metrics); |
333 | clnt->cl_metrics = NULL; | 334 | clnt->cl_metrics = NULL; |
334 | if (!IS_ERR(clnt->cl_dentry)) { | ||
335 | dput(clnt->cl_dentry); | ||
336 | rpc_put_mount(); | ||
337 | } | ||
338 | kfree(clnt); | 335 | kfree(clnt); |
339 | return 0; | 336 | return 0; |
340 | } | 337 | } |
@@ -1184,6 +1181,17 @@ call_verify(struct rpc_task *task) | |||
1184 | u32 *p = iov->iov_base, n; | 1181 | u32 *p = iov->iov_base, n; |
1185 | int error = -EACCES; | 1182 | int error = -EACCES; |
1186 | 1183 | ||
1184 | if ((task->tk_rqstp->rq_rcv_buf.len & 3) != 0) { | ||
1185 | /* RFC-1014 says that the representation of XDR data must be a | ||
1186 | * multiple of four bytes | ||
1187 | * - if it isn't pointer subtraction in the NFS client may give | ||
1188 | * undefined results | ||
1189 | */ | ||
1190 | printk(KERN_WARNING | ||
1191 | "call_verify: XDR representation not a multiple of" | ||
1192 | " 4 bytes: 0x%x\n", task->tk_rqstp->rq_rcv_buf.len); | ||
1193 | goto out_eio; | ||
1194 | } | ||
1187 | if ((len -= 3) < 0) | 1195 | if ((len -= 3) < 0) |
1188 | goto out_overflow; | 1196 | goto out_overflow; |
1189 | p += 1; /* skip XID */ | 1197 | p += 1; /* skip XID */ |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index a3bd2db2e024..0b1a1ac8a4bc 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -539,6 +539,7 @@ repeat: | |||
539 | rpc_close_pipes(dentry->d_inode); | 539 | rpc_close_pipes(dentry->d_inode); |
540 | simple_unlink(dir, dentry); | 540 | simple_unlink(dir, dentry); |
541 | } | 541 | } |
542 | inode_dir_notify(dir, DN_DELETE); | ||
542 | dput(dentry); | 543 | dput(dentry); |
543 | } while (n); | 544 | } while (n); |
544 | goto repeat; | 545 | goto repeat; |
@@ -610,8 +611,8 @@ __rpc_rmdir(struct inode *dir, struct dentry *dentry) | |||
610 | int error; | 611 | int error; |
611 | 612 | ||
612 | shrink_dcache_parent(dentry); | 613 | shrink_dcache_parent(dentry); |
613 | if (dentry->d_inode) | 614 | if (d_unhashed(dentry)) |
614 | rpc_close_pipes(dentry->d_inode); | 615 | return 0; |
615 | if ((error = simple_rmdir(dir, dentry)) != 0) | 616 | if ((error = simple_rmdir(dir, dentry)) != 0) |
616 | return error; | 617 | return error; |
617 | if (!error) { | 618 | if (!error) { |
@@ -684,28 +685,20 @@ err_dput: | |||
684 | } | 685 | } |
685 | 686 | ||
686 | int | 687 | int |
687 | rpc_rmdir(char *path) | 688 | rpc_rmdir(struct dentry *dentry) |
688 | { | 689 | { |
689 | struct nameidata nd; | 690 | struct dentry *parent; |
690 | struct dentry *dentry; | ||
691 | struct inode *dir; | 691 | struct inode *dir; |
692 | int error; | 692 | int error; |
693 | 693 | ||
694 | if ((error = rpc_lookup_parent(path, &nd)) != 0) | 694 | parent = dget_parent(dentry); |
695 | return error; | 695 | dir = parent->d_inode; |
696 | dir = nd.dentry->d_inode; | ||
697 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 696 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
698 | dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); | ||
699 | if (IS_ERR(dentry)) { | ||
700 | error = PTR_ERR(dentry); | ||
701 | goto out_release; | ||
702 | } | ||
703 | rpc_depopulate(dentry); | 697 | rpc_depopulate(dentry); |
704 | error = __rpc_rmdir(dir, dentry); | 698 | error = __rpc_rmdir(dir, dentry); |
705 | dput(dentry); | 699 | dput(dentry); |
706 | out_release: | ||
707 | mutex_unlock(&dir->i_mutex); | 700 | mutex_unlock(&dir->i_mutex); |
708 | rpc_release_path(&nd); | 701 | dput(parent); |
709 | return error; | 702 | return error; |
710 | } | 703 | } |
711 | 704 | ||
@@ -746,32 +739,26 @@ err_dput: | |||
746 | } | 739 | } |
747 | 740 | ||
748 | int | 741 | int |
749 | rpc_unlink(char *path) | 742 | rpc_unlink(struct dentry *dentry) |
750 | { | 743 | { |
751 | struct nameidata nd; | 744 | struct dentry *parent; |
752 | struct dentry *dentry; | ||
753 | struct inode *dir; | 745 | struct inode *dir; |
754 | int error; | 746 | int error = 0; |
755 | 747 | ||
756 | if ((error = rpc_lookup_parent(path, &nd)) != 0) | 748 | parent = dget_parent(dentry); |
757 | return error; | 749 | dir = parent->d_inode; |
758 | dir = nd.dentry->d_inode; | ||
759 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); | 750 | mutex_lock_nested(&dir->i_mutex, I_MUTEX_PARENT); |
760 | dentry = lookup_one_len(nd.last.name, nd.dentry, nd.last.len); | 751 | if (!d_unhashed(dentry)) { |
761 | if (IS_ERR(dentry)) { | 752 | d_drop(dentry); |
762 | error = PTR_ERR(dentry); | 753 | if (dentry->d_inode) { |
763 | goto out_release; | 754 | rpc_close_pipes(dentry->d_inode); |
764 | } | 755 | error = simple_unlink(dir, dentry); |
765 | d_drop(dentry); | 756 | } |
766 | if (dentry->d_inode) { | 757 | inode_dir_notify(dir, DN_DELETE); |
767 | rpc_close_pipes(dentry->d_inode); | ||
768 | error = simple_unlink(dir, dentry); | ||
769 | } | 758 | } |
770 | dput(dentry); | 759 | dput(dentry); |
771 | inode_dir_notify(dir, DN_DELETE); | ||
772 | out_release: | ||
773 | mutex_unlock(&dir->i_mutex); | 760 | mutex_unlock(&dir->i_mutex); |
774 | rpc_release_path(&nd); | 761 | dput(parent); |
775 | return error; | 762 | return error; |
776 | } | 763 | } |
777 | 764 | ||