From: Trond Myklebust Date: Fri, 28 Jun 2013 20:29:51 +0000 (-0400) Subject: Merge branch 'labeled-nfs' into linux-next X-Git-Url: https://rtime.felk.cvut.cz/gitweb/linux-imx.git/commitdiff_plain/959d921f5eb8878ea16049a7f6e9bcbb6dfbcb88 Merge branch 'labeled-nfs' into linux-next * labeled-nfs: NFS: Apply v4.1 capabilities to v4.2 NFS: Add in v4.2 callback operation NFS: Make callbacks minor version generic Kconfig: Add Kconfig entry for Labeled NFS V4 client NFS: Extend NFS xattr handlers to accept the security namespace NFS: Client implementation of Labeled-NFS NFS: Add label lifecycle management NFS:Add labels to client function prototypes NFSv4: Extend fattr bitmaps to support all 3 words NFSv4: Introduce new label structure NFSv4: Add label recommended attribute and NFSv4 flags NFSv4.2: Added NFS v4.2 support to the NFS client SELinux: Add new labeling type native labels LSM: Add flags field to security_sb_set_mnt_opts for in kernel mount data. Security: Add Hook to test if the particular xattr is part of a MAC model. Security: Add hook to calculate context based on a negative dentry. NFS: Add NFSv4.2 protocol constants Conflicts: fs/nfs/nfs4proc.c --- 959d921f5eb8878ea16049a7f6e9bcbb6dfbcb88 diff --cc fs/nfs/nfs4proc.c index 6d46f966d169,c0d3123b6eba..d95616f140ad --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@@ -77,17 -77,66 +77,68 @@@ static int _nfs4_recover_proc_open(stru static int nfs4_do_fsinfo(struct nfs_server *, struct nfs_fh *, struct nfs_fsinfo *); static int nfs4_async_handle_error(struct rpc_task *, const struct nfs_server *, struct nfs4_state *); static void nfs_fixup_referral_attributes(struct nfs_fattr *fattr); - static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *); - static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr); + static int nfs4_proc_getattr(struct nfs_server *, struct nfs_fh *, struct nfs_fattr *, struct nfs4_label *label); + static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, struct nfs_fattr *fattr, struct nfs4_label *label); static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, struct nfs_fattr *fattr, struct iattr *sattr, - struct nfs4_state *state); + struct nfs4_state *state, struct nfs4_label *ilabel, + struct nfs4_label *olabel); #ifdef CONFIG_NFS_V4_1 -static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *); -static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *); +static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *, + struct rpc_cred *); +static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *, + struct rpc_cred *); #endif + + #ifdef CONFIG_NFS_V4_SECURITY_LABEL + static inline struct nfs4_label * + nfs4_label_init_security(struct inode *dir, struct dentry *dentry, + struct iattr *sattr, struct nfs4_label *label) + { + int err; + + if (label == NULL) + return NULL; + + if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL) == 0) + return NULL; + + if (NFS_SERVER(dir)->nfs_client->cl_minorversion < 2) + return NULL; + + err = security_dentry_init_security(dentry, sattr->ia_mode, + &dentry->d_name, (void **)&label->label, &label->len); + if (err == 0) + return label; + + return NULL; + } + static inline void + nfs4_label_release_security(struct nfs4_label *label) + { + if (label) + security_release_secctx(label->label, label->len); + } + static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label) + { + if (label) + return server->attr_bitmask; + + return server->attr_bitmask_nl; + } + #else + static inline struct nfs4_label * + nfs4_label_init_security(struct inode *dir, struct dentry *dentry, + struct iattr *sattr, struct nfs4_label *l) + { return NULL; } + static inline void + nfs4_label_release_security(struct nfs4_label *label) + { return; } + static inline u32 * + nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label) + { return server->attr_bitmask; } + #endif + /* Prevent leaks of NFSv4 errors into userland */ static int nfs4_map_errors(int err) { @@@ -2015,19 -2049,21 +2086,21 @@@ out * Returns a referenced nfs4_state */ static int _nfs4_do_open(struct inode *dir, - struct dentry *dentry, - fmode_t fmode, + struct nfs_open_context *ctx, int flags, - struct iattr *sattr) + struct iattr *sattr, - struct nfs4_label *label, - struct rpc_cred *cred, - struct nfs4_state **res, - struct nfs4_threshold **ctx_th) ++ struct nfs4_label *label) { struct nfs4_state_owner *sp; struct nfs4_state *state = NULL; struct nfs_server *server = NFS_SERVER(dir); struct nfs4_opendata *opendata; + struct dentry *dentry = ctx->dentry; + struct rpc_cred *cred = ctx->cred; + struct nfs4_threshold **ctx_th = &ctx->mdsthreshold; + fmode_t fmode = ctx->mode & (FMODE_READ|FMODE_WRITE|FMODE_EXEC); enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL; + struct nfs4_label *olabel = NULL; int status; /* Protect against reboot recovery conflicts */ @@@ -2059,10 -2103,9 +2140,10 @@@ if (dentry->d_inode != NULL) opendata->state = nfs4_get_open_state(dentry->d_inode, sp); - status = _nfs4_open_and_get_state(opendata, fmode, flags, &state); + status = _nfs4_open_and_get_state(opendata, fmode, flags, ctx); if (status != 0) - goto err_opendata_put; + goto err_free_label; + state = ctx->state; if ((opendata->o_arg.open_flags & O_EXCL) && (opendata->o_arg.createmode != NFS4_CREATE_GUARDED)) { @@@ -2083,9 -2128,14 +2166,13 @@@ kfree(opendata->f_attr.mdsthreshold); opendata->f_attr.mdsthreshold = NULL; + nfs4_label_free(olabel); + nfs4_opendata_put(opendata); nfs4_put_state_owner(sp); - *res = state; return 0; + err_free_label: + nfs4_label_free(olabel); err_opendata_put: kfree(opendata->f_attr.mdsthreshold); nfs4_opendata_put(opendata); @@@ -2097,18 -2148,23 +2184,19 @@@ out_err static struct nfs4_state *nfs4_do_open(struct inode *dir, - struct dentry *dentry, - fmode_t fmode, + struct nfs_open_context *ctx, int flags, - struct iattr *sattr) + struct iattr *sattr, - struct nfs4_label *label, - struct rpc_cred *cred, - struct nfs4_threshold **ctx_th) ++ struct nfs4_label *label) { struct nfs_server *server = NFS_SERVER(dir); struct nfs4_exception exception = { }; struct nfs4_state *res; int status; - fmode &= FMODE_READ|FMODE_WRITE|FMODE_EXEC; do { - status = _nfs4_do_open(dir, ctx, flags, sattr); - status = _nfs4_do_open(dir, dentry, fmode, flags, sattr, label, cred, - &res, ctx_th); ++ status = _nfs4_do_open(dir, ctx, flags, sattr, label); + res = ctx->state; if (status == 0) break; /* NOTE: BAD_SEQID means the server and client disagree about the @@@ -2458,12 -2522,20 +2554,18 @@@ static struct inode nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr) { struct nfs4_state *state; + struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL; + + label = nfs4_label_init_security(dir, ctx->dentry, attr, &l); /* Protect against concurrent sillydeletes */ - state = nfs4_do_open(dir, ctx, open_flags, attr); - state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr, label, - ctx->cred, &ctx->mdsthreshold); ++ state = nfs4_do_open(dir, ctx, open_flags, attr, label); + + nfs4_label_release_security(label); + if (IS_ERR(state)) return ERR_CAST(state); - ctx->state = state; - return igrab(state->inode); + return state->inode; } static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) @@@ -3067,13 -3183,22 +3213,16 @@@ nfs4_proc_create(struct inode *dir, str if (IS_ERR(ctx)) return PTR_ERR(ctx); + ilabel = nfs4_label_init_security(dir, dentry, sattr, &l); + sattr->ia_mode &= ~current_umask(); - state = nfs4_do_open(dir, ctx, flags, sattr); - state = nfs4_do_open(dir, dentry, ctx->mode, - flags, sattr, ilabel, ctx->cred, - &ctx->mdsthreshold); - d_drop(dentry); ++ state = nfs4_do_open(dir, ctx, flags, sattr, ilabel); if (IS_ERR(state)) { status = PTR_ERR(state); goto out; } - d_add(dentry, igrab(state->inode)); - nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); - ctx->state = state; out: + nfs4_label_release_security(ilabel); put_nfs_open_context(ctx); return status; }