From b77a4b2edb29459ad039a1d8f5769bb2192acae1 Mon Sep 17 00:00:00 2001 From: Kinglong Mee Date: Sun, 15 Mar 2015 23:13:32 +0800 Subject: NFSD: Using path_equal() for checking two paths Signed-off-by: Kinglong Mee Signed-off-by: J. Bruce Fields --- fs/nfsd/export.c | 3 +-- fs/nfsd/nfs4xdr.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index c3e3b6e55ae2..2911f519fe64 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -691,8 +691,7 @@ static int svc_export_match(struct cache_head *a, struct cache_head *b) struct svc_export *orig = container_of(a, struct svc_export, h); struct svc_export *new = container_of(b, struct svc_export, h); return orig->ex_client == new->ex_client && - orig->ex_path.dentry == new->ex_path.dentry && - orig->ex_path.mnt == new->ex_path.mnt; + path_equal(&orig->ex_path, &new->ex_path); } static void svc_export_init(struct cache_head *cnew, struct cache_head *citem) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 5fb7e78169a6..5c0aa74cba86 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2020,7 +2020,7 @@ static __be32 nfsd4_encode_path(struct xdr_stream *xdr, * dentries/path components in an array. */ for (;;) { - if (cur.dentry == root->dentry && cur.mnt == root->mnt) + if (path_equal(&cur, root)) break; if (cur.dentry == cur.mnt->mnt_root) { if (follow_up(&cur)) -- cgit From beaca2347f1b7986376e3906dfa7615a9d6f53d8 Mon Sep 17 00:00:00 2001 From: Kinglong Mee Date: Sun, 15 Mar 2015 23:35:11 +0800 Subject: NFSD: Use correct reply size calculating function ALLOCATE/DEALLOCATE only reply one status value to client, so, using nfsd4_only_status_rsize for reply size calculating. Signed-off-by: Kinglong Mee Reviewed-by: Anna Schumaker Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4proc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 92b9d97aff4f..4449359fffa2 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -2282,13 +2282,13 @@ static struct nfsd4_operation nfsd4_ops[] = { .op_func = (nfsd4op_func)nfsd4_allocate, .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_ALLOCATE", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize, + .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, }, [OP_DEALLOCATE] = { .op_func = (nfsd4op_func)nfsd4_deallocate, .op_flags = OP_MODIFIES_SOMETHING | OP_CACHEME, .op_name = "OP_DEALLOCATE", - .op_rsize_bop = (nfsd4op_rsize)nfsd4_write_rsize, + .op_rsize_bop = (nfsd4op_rsize)nfsd4_only_status_rsize, }, [OP_SEEK] = { .op_func = (nfsd4op_func)nfsd4_seek, -- cgit From fc26c3860a6a4a9396f401024f1cc91a95a59143 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 23 Mar 2015 10:53:43 -0400 Subject: nfsd: remove bogus setting of status in nfsd4_process_open2 status is always reset after this (and it doesn't make much sense there anyway). Signed-off-by: Jeff Layton Reviewed-by: Christoph Hellwig Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 1 - 1 file changed, 1 deletion(-) (limited to 'fs') diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 8ba1d888f1e6..1596b1352bc5 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4049,7 +4049,6 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf status = nfserr_bad_stateid; if (nfsd4_is_deleg_cur(open)) goto out; - status = nfserr_jukebox; } /* -- cgit From 4229789993ee23bf35ee87546655bbbb6013569a Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Mon, 23 Mar 2015 10:53:44 -0400 Subject: nfsd: remove unused status arg to nfsd4_cleanup_open_state Signed-off-by: Jeff Layton Reviewed-by: Christoph Hellwig Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/nfs4state.c | 2 +- fs/nfsd/xdr4.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 4449359fffa2..8d7260ebb611 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -470,7 +470,7 @@ out: fh_put(resfh); kfree(resfh); } - nfsd4_cleanup_open_state(cstate, open, status); + nfsd4_cleanup_open_state(cstate, open); nfsd4_bump_seqid(cstate, status); return status; } diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 1596b1352bc5..fd875b6107ba 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4117,7 +4117,7 @@ out: } void nfsd4_cleanup_open_state(struct nfsd4_compound_state *cstate, - struct nfsd4_open *open, __be32 status) + struct nfsd4_open *open) { if (open->op_openowner) { struct nfs4_stateowner *so = &open->op_openowner->oo_owner; diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 0bda93e58e1b..83e80d6d94a6 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h @@ -683,7 +683,7 @@ extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open); extern void nfsd4_cstate_clear_replay(struct nfsd4_compound_state *cstate); extern void nfsd4_cleanup_open_state(struct nfsd4_compound_state *cstate, - struct nfsd4_open *open, __be32 status); + struct nfsd4_open *open); extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *, struct nfsd4_open_confirm *oc); extern __be32 nfsd4_close(struct svc_rqst *rqstp, -- cgit From 629b8729cc2ca8fde7deb008dab09f3ad19fed52 Mon Sep 17 00:00:00 2001 From: Chengyu Song Date: Wed, 25 Mar 2015 16:37:07 -0400 Subject: nfsd: NFSD_FAULT_INJECTION depends on DEBUG_FS NFSD_FAULT_INJECTION depends on DEBUG_FS, otherwise the debugfs_create_* interface may return unexpected error -ENODEV, and cause system crash. Signed-off-by: Chengyu Song Signed-off-by: J. Bruce Fields --- fs/nfsd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'fs') diff --git a/fs/nfsd/Kconfig b/fs/nfsd/Kconfig index 683bf718aead..8b87b7a0eab5 100644 --- a/fs/nfsd/Kconfig +++ b/fs/nfsd/Kconfig @@ -107,7 +107,7 @@ config NFSD_V4_SECURITY_LABEL config NFSD_FAULT_INJECTION bool "NFS server manual fault injection" - depends on NFSD_V4 && DEBUG_KERNEL + depends on NFSD_V4 && DEBUG_KERNEL && DEBUG_FS help This option enables support for manually injecting faults into the NFS server. This is intended to be used for -- cgit From b14f4f7e61aaa4437a42e2e11055fc01782a15bf Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Thu, 26 Mar 2015 10:37:51 -0400 Subject: nfsd: allow setting acls with unenforceable DENYs We've been refusing ACLs that DENY permissions that we can't effectively deny. (For example, we can't deny permission to read attributes.) Andreas points out that any DENY of Window's "read", "write", or "modify" permissions would trigger this. That would be annoying. So maybe we should be a little less paranoid, and ignore entirely the permissions that are meaningless to us. Reported-by: Andreas Gruenbacher Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4acl.c | 50 +------------------------------------------------- 1 file changed, 1 insertion(+), 49 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c index 59fd76651781..eaf4605a4b9e 100644 --- a/fs/nfsd/nfs4acl.c +++ b/fs/nfsd/nfs4acl.c @@ -499,43 +499,13 @@ static inline void add_to_mask(struct posix_acl_state *state, struct posix_ace_s state->mask.allow |= astate->allow; } -/* - * Certain bits (SYNCHRONIZE, DELETE, WRITE_OWNER, READ/WRITE_NAMED_ATTRS, - * READ_ATTRIBUTES, READ_ACL) are currently unenforceable and don't translate - * to traditional read/write/execute permissions. - * - * It's problematic to reject acls that use certain mode bits, because it - * places the burden on users to learn the rules about which bits one - * particular server sets, without giving the user a lot of help--we return an - * error that could mean any number of different things. To make matters - * worse, the problematic bits might be introduced by some application that's - * automatically mapping from some other acl model. - * - * So wherever possible we accept anything, possibly erring on the side of - * denying more permissions than necessary. - * - * However we do reject *explicit* DENY's of a few bits representing - * permissions we could never deny: - */ - -static inline int check_deny(u32 mask, int isowner) -{ - if (mask & (NFS4_ACE_READ_ATTRIBUTES | NFS4_ACE_READ_ACL)) - return -EINVAL; - if (!isowner) - return 0; - if (mask & (NFS4_ACE_WRITE_ATTRIBUTES | NFS4_ACE_WRITE_ACL)) - return -EINVAL; - return 0; -} - static struct posix_acl * posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) { struct posix_acl_entry *pace; struct posix_acl *pacl; int nace; - int i, error = 0; + int i; /* * ACLs with no ACEs are treated differently in the inheritable @@ -560,17 +530,11 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) pace = pacl->a_entries; pace->e_tag = ACL_USER_OBJ; - error = check_deny(state->owner.deny, 1); - if (error) - goto out_err; low_mode_from_nfs4(state->owner.allow, &pace->e_perm, flags); for (i=0; i < state->users->n; i++) { pace++; pace->e_tag = ACL_USER; - error = check_deny(state->users->aces[i].perms.deny, 0); - if (error) - goto out_err; low_mode_from_nfs4(state->users->aces[i].perms.allow, &pace->e_perm, flags); pace->e_uid = state->users->aces[i].uid; @@ -579,18 +543,12 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) pace++; pace->e_tag = ACL_GROUP_OBJ; - error = check_deny(state->group.deny, 0); - if (error) - goto out_err; low_mode_from_nfs4(state->group.allow, &pace->e_perm, flags); add_to_mask(state, &state->group); for (i=0; i < state->groups->n; i++) { pace++; pace->e_tag = ACL_GROUP; - error = check_deny(state->groups->aces[i].perms.deny, 0); - if (error) - goto out_err; low_mode_from_nfs4(state->groups->aces[i].perms.allow, &pace->e_perm, flags); pace->e_gid = state->groups->aces[i].gid; @@ -605,15 +563,9 @@ posix_state_to_acl(struct posix_acl_state *state, unsigned int flags) pace++; pace->e_tag = ACL_OTHER; - error = check_deny(state->other.deny, 0); - if (error) - goto out_err; low_mode_from_nfs4(state->other.allow, &pace->e_perm, flags); return pacl; -out_err: - posix_acl_release(pacl); - return ERR_PTR(error); } static inline void allow_bits(struct posix_ace_state *astate, u32 mask) -- cgit From 1ec8c0c47f63b4af66e3615618f842267ac88b4a Mon Sep 17 00:00:00 2001 From: Kinglong Mee Date: Sat, 28 Mar 2015 23:46:09 +0800 Subject: nfsd: Remove duplicate macro define for max sec label length NFS4_MAXLABELLEN has defined for sec label max length, use it directly. Signed-off-by: Kinglong Mee Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/nfs4xdr.c | 2 +- fs/nfsd/xdr4.h | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 8d7260ebb611..b401da386604 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1815,7 +1815,7 @@ static inline u32 nfsd4_getattr_rsize(struct svc_rqst *rqstp, bmap0 &= ~FATTR4_WORD0_FILEHANDLE; } if (bmap2 & FATTR4_WORD2_SECURITY_LABEL) { - ret += NFSD4_MAX_SEC_LABEL_LEN + 12; + ret += NFS4_MAXLABELLEN + 12; bmap2 &= ~FATTR4_WORD2_SECURITY_LABEL; } /* diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 5c0aa74cba86..cea6c529434f 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -424,7 +424,7 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, len += 4; dummy32 = be32_to_cpup(p++); READ_BUF(dummy32); - if (dummy32 > NFSD4_MAX_SEC_LABEL_LEN) + if (dummy32 > NFS4_MAXLABELLEN) return nfserr_badlabel; len += (XDR_QUADLEN(dummy32) << 2); READMEM(buf, dummy32); diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index 83e80d6d94a6..556ce2e47555 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h @@ -40,7 +40,6 @@ #include "state.h" #include "nfsd.h" -#define NFSD4_MAX_SEC_LABEL_LEN 2048 #define NFSD4_MAX_TAGLEN 128 #define XDR_LEN(n) (((n) + 3) & ~3) -- cgit From 9b3075c59f858d64478f46a15daa6ecda3cf2318 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 1 Apr 2015 01:37:05 -0700 Subject: nfsd: add NFSEXP_PNFS to the exflags array Signed-off-by: J. Bruce Fields --- fs/nfsd/export.c | 1 + 1 file changed, 1 insertion(+) (limited to 'fs') diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 2911f519fe64..900c3ae94adc 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -1158,6 +1158,7 @@ static struct flags { { NFSEXP_NOSUBTREECHECK, {"no_subtree_check", ""}}, { NFSEXP_NOAUTHNLM, {"insecure_locks", ""}}, { NFSEXP_V4ROOT, {"v4root", ""}}, + { NFSEXP_PNFS, {"pnfs", ""}}, { 0, {"", ""}} }; -- cgit From 5ba4a25ab7b13be528b23f85182f4d09cf7f71ad Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 3 Apr 2015 16:24:27 -0400 Subject: nfsd4: disallow ALLOCATE with special stateids vfs_fallocate will hit a NULL dereference if the client tries an ALLOCATE or DEALLOCATE with a special stateid. Fix that. (We also depend on the open to have broken any conflicting leases or delegations for us.) (If it turns out we need to allow special stateid's then we could do a temporary open here in the special-stateid case, as we do for read and write. For now I'm assuming it's not necessary.) Fixes: 95d871f03cae "nfsd: Add ALLOCATE support" Cc: stable@vger.kernel.org Cc: Anna Schumaker Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4proc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index b401da386604..d0848fc6529e 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1030,6 +1030,8 @@ nfsd4_fallocate(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, dprintk("NFSD: nfsd4_fallocate: couldn't process stateid!\n"); return status; } + if (!file) + return nfserr_bad_stateid; status = nfsd4_vfs_fallocate(rqstp, &cstate->current_fh, file, fallocate->falloc_offset, -- cgit From 980608fb50aea34993ba956b71cd4602aa42b14b Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Tue, 21 Apr 2015 15:25:39 -0400 Subject: nfsd4: disallow SEEK with special stateids If the client uses a special stateid then we'll pass a NULL file to vfs_llseek. Fixes: 24bab491220f " NFSD: Implement SEEK" Cc: Anna Schumaker Cc: stable@vger.kernel.org Reported-by: Christoph Hellwig Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4proc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'fs') diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index d0848fc6529e..4a8314f08a0e 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1071,6 +1071,8 @@ nfsd4_seek(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, dprintk("NFSD: nfsd4_seek: couldn't process stateid!\n"); return status; } + if (!file) + return nfserr_bad_stateid; switch (seek->seek_whence) { case NFS4_CONTENT_DATA: -- cgit From 6e4891dc289cd191d46ab7ba1dcb29646644f9ca Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Fri, 3 Apr 2015 17:19:41 -0400 Subject: nfsd4: fix READ permission checking In the case we already have a struct file (derived from a stateid), we still need to do permission-checking; otherwise an unauthorized user could gain access to a file by sniffing or guessing somebody else's stateid. Cc: stable@vger.kernel.org Fixes: dc97618ddda9 "nfsd4: separate splice and readv cases" Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4xdr.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index cea6c529434f..a45032ce7b80 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -3422,6 +3422,7 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, unsigned long maxcount; struct xdr_stream *xdr = &resp->xdr; struct file *file = read->rd_filp; + struct svc_fh *fhp = read->rd_fhp; int starting_len = xdr->buf->len; struct raparms *ra; __be32 *p; @@ -3445,12 +3446,15 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, maxcount = min_t(unsigned long, maxcount, (xdr->buf->buflen - xdr->buf->len)); maxcount = min_t(unsigned long, maxcount, read->rd_length); - if (!read->rd_filp) { + if (read->rd_filp) + err = nfsd_permission(resp->rqstp, fhp->fh_export, + fhp->fh_dentry, + NFSD_MAY_READ|NFSD_MAY_OWNER_OVERRIDE); + else err = nfsd_get_tmp_read_open(resp->rqstp, read->rd_fhp, &file, &ra); - if (err) - goto err_truncate; - } + if (err) + goto err_truncate; if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) err = nfsd4_encode_splice_read(resp, read, file, maxcount); -- cgit From 135dd002c23054aaa056ea3162c1e0356905c195 Mon Sep 17 00:00:00 2001 From: Mark Salter Date: Mon, 6 Apr 2015 09:46:00 -0400 Subject: nfsd: eliminate NFSD_DEBUG Commit f895b252d4edf ("sunrpc: eliminate RPC_DEBUG") introduced use of IS_ENABLED() in a uapi header which leads to a build failure for userspace apps trying to use : linux/nfsd/debug.h:18:15: error: missing binary operator before token "(" #if IS_ENABLED(CONFIG_SUNRPC_DEBUG) ^ Since this was only used to define NFSD_DEBUG if CONFIG_SUNRPC_DEBUG is enabled, replace instances of NFSD_DEBUG with CONFIG_SUNRPC_DEBUG. Cc: stable@vger.kernel.org Fixes: f895b252d4edf "sunrpc: eliminate RPC_DEBUG" Signed-off-by: Mark Salter Reviewed-by: Jeff Layton Signed-off-by: J. Bruce Fields --- fs/lockd/svcsubs.c | 2 +- fs/nfsd/nfs4state.c | 2 +- fs/nfsd/nfsd.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'fs') diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index 665ef5a05183..a563ddbc19e6 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c @@ -31,7 +31,7 @@ static struct hlist_head nlm_files[FILE_NRHASH]; static DEFINE_MUTEX(nlm_file_mutex); -#ifdef NFSD_DEBUG +#ifdef CONFIG_SUNRPC_DEBUG static inline void nlm_debug_print_fh(char *msg, struct nfs_fh *f) { u32 *fhp = (u32*)f->data; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index fd875b6107ba..693495551bb2 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1139,7 +1139,7 @@ hash_sessionid(struct nfs4_sessionid *sessionid) return sid->sequence % SESSION_HASH_SIZE; } -#ifdef NFSD_DEBUG +#ifdef CONFIG_SUNRPC_DEBUG static inline void dump_sessionid(const char *fn, struct nfs4_sessionid *sessionid) { diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 565c4da1a9eb..cf980523898b 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -24,7 +24,7 @@ #include "export.h" #undef ifdebug -#ifdef NFSD_DEBUG +#ifdef CONFIG_SUNRPC_DEBUG # define ifdebug(flag) if (nfsd_debug & NFSDDBG_##flag) #else # define ifdebug(flag) if (0) -- cgit From bb7ffbf29e76b89a86ca4c3ee0d4690641f2f772 Mon Sep 17 00:00:00 2001 From: Giuseppe Cantavenera Date: Mon, 20 Apr 2015 18:00:08 +0200 Subject: nfsd: fix nsfd startup race triggering BUG_ON nfsd triggered a BUG_ON in net_generic(...) when rpc_pipefs_event(...) in fs/nfsd/nfs4recover.c was called before assigning ntfsd_net_id. The following was observed on a MIPS 32-core processor: kernel: Call Trace: kernel: [] rpc_pipefs_event+0x7c/0x158 [nfsd] kernel: [] notifier_call_chain+0x70/0xb8 kernel: [] __blocking_notifier_call_chain+0x4c/0x70 kernel: [] rpc_fill_super+0xf8/0x1a0 kernel: [] mount_ns+0xb4/0xf0 kernel: [] mount_fs+0x50/0x1f8 kernel: [] vfs_kern_mount+0x58/0xf0 kernel: [] do_mount+0x27c/0xa28 kernel: [] SyS_mount+0x98/0xe8 kernel: [] handle_sys64+0x44/0x68 kernel: kernel: Code: 0040f809 00000000 2e020001 <00020336> 3c12c00d 3c02801a de100000 6442eb98 0040f809 kernel: ---[ end trace 7471374335809536 ]--- Fixed this behaviour by calling register_pernet_subsys(&nfsd_net_ops) before registering rpc_pipefs_event(...) with the notifier chain. Signed-off-by: Giuseppe Cantavenera Signed-off-by: Lorenzo Restelli Reviewed-by: Kinlong Mee Cc: stable@vger.kernel.org Signed-off-by: J. Bruce Fields --- fs/nfsd/nfsctl.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'fs') diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index aa47d75ddb26..9690cb4dd588 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -1250,15 +1250,15 @@ static int __init init_nfsd(void) int retval; printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); - retval = register_cld_notifier(); - if (retval) - return retval; retval = register_pernet_subsys(&nfsd_net_ops); if (retval < 0) - goto out_unregister_notifier; - retval = nfsd4_init_slabs(); + return retval; + retval = register_cld_notifier(); if (retval) goto out_unregister_pernet; + retval = nfsd4_init_slabs(); + if (retval) + goto out_unregister_notifier; retval = nfsd4_init_pnfs(); if (retval) goto out_free_slabs; @@ -1290,10 +1290,10 @@ out_exit_pnfs: nfsd4_exit_pnfs(); out_free_slabs: nfsd4_free_slabs(); -out_unregister_pernet: - unregister_pernet_subsys(&nfsd_net_ops); out_unregister_notifier: unregister_cld_notifier(); +out_unregister_pernet: + unregister_pernet_subsys(&nfsd_net_ops); return retval; } @@ -1308,8 +1308,8 @@ static void __exit exit_nfsd(void) nfsd4_exit_pnfs(); nfsd_fault_inject_cleanup(); unregister_filesystem(&nfsd_fs_type); - unregister_pernet_subsys(&nfsd_net_ops); unregister_cld_notifier(); + unregister_pernet_subsys(&nfsd_net_ops); } MODULE_AUTHOR("Olaf Kirch "); -- cgit