diff options
author | Trond Myklebust <trond.myklebust@hammerspace.com> | 2019-06-27 06:30:48 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@hammerspace.com> | 2019-07-06 14:54:25 -0400 |
commit | 1bf85d8c98756421e29b9990469ee63bb0bc87cc (patch) | |
tree | c27a2436eba998457011c275881a3286a4b7d7ac | |
parent | bcc0e65f47def010d8d1c4cf09bdc698fe061b77 (diff) |
NFSv4: Handle open for execute correctly
When mapping the NFSv4 context to an open mode and access mode,
we need to treat the FMODE_EXEC flag differently. For the open
mode, FMODE_EXEC means we need read share access. For the access
mode checking, we need to verify that the user actually has
execute access.
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
-rw-r--r-- | fs/nfs/nfs4proc.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 6418cb6c079b..26626ea1f197 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -1165,6 +1165,18 @@ static bool nfs4_clear_cap_atomic_open_v1(struct nfs_server *server, | |||
1165 | return true; | 1165 | return true; |
1166 | } | 1166 | } |
1167 | 1167 | ||
1168 | static fmode_t _nfs4_ctx_to_accessmode(const struct nfs_open_context *ctx) | ||
1169 | { | ||
1170 | return ctx->mode & (FMODE_READ|FMODE_WRITE|FMODE_EXEC); | ||
1171 | } | ||
1172 | |||
1173 | static fmode_t _nfs4_ctx_to_openmode(const struct nfs_open_context *ctx) | ||
1174 | { | ||
1175 | fmode_t ret = ctx->mode & (FMODE_READ|FMODE_WRITE); | ||
1176 | |||
1177 | return (ctx->mode & FMODE_EXEC) ? FMODE_READ | ret : ret; | ||
1178 | } | ||
1179 | |||
1168 | static u32 | 1180 | static u32 |
1169 | nfs4_map_atomic_open_share(struct nfs_server *server, | 1181 | nfs4_map_atomic_open_share(struct nfs_server *server, |
1170 | fmode_t fmode, int openflags) | 1182 | fmode_t fmode, int openflags) |
@@ -2900,14 +2912,13 @@ static unsigned nfs4_exclusive_attrset(struct nfs4_opendata *opendata, | |||
2900 | } | 2912 | } |
2901 | 2913 | ||
2902 | static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, | 2914 | static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, |
2903 | fmode_t fmode, | 2915 | int flags, struct nfs_open_context *ctx) |
2904 | int flags, | ||
2905 | struct nfs_open_context *ctx) | ||
2906 | { | 2916 | { |
2907 | struct nfs4_state_owner *sp = opendata->owner; | 2917 | struct nfs4_state_owner *sp = opendata->owner; |
2908 | struct nfs_server *server = sp->so_server; | 2918 | struct nfs_server *server = sp->so_server; |
2909 | struct dentry *dentry; | 2919 | struct dentry *dentry; |
2910 | struct nfs4_state *state; | 2920 | struct nfs4_state *state; |
2921 | fmode_t acc_mode = _nfs4_ctx_to_accessmode(ctx); | ||
2911 | unsigned int seq; | 2922 | unsigned int seq; |
2912 | int ret; | 2923 | int ret; |
2913 | 2924 | ||
@@ -2946,7 +2957,8 @@ static int _nfs4_open_and_get_state(struct nfs4_opendata *opendata, | |||
2946 | /* Parse layoutget results before we check for access */ | 2957 | /* Parse layoutget results before we check for access */ |
2947 | pnfs_parse_lgopen(state->inode, opendata->lgp, ctx); | 2958 | pnfs_parse_lgopen(state->inode, opendata->lgp, ctx); |
2948 | 2959 | ||
2949 | ret = nfs4_opendata_access(sp->so_cred, opendata, state, fmode, flags); | 2960 | ret = nfs4_opendata_access(sp->so_cred, opendata, state, |
2961 | acc_mode, flags); | ||
2950 | if (ret != 0) | 2962 | if (ret != 0) |
2951 | goto out; | 2963 | goto out; |
2952 | 2964 | ||
@@ -2978,7 +2990,7 @@ static int _nfs4_do_open(struct inode *dir, | |||
2978 | struct dentry *dentry = ctx->dentry; | 2990 | struct dentry *dentry = ctx->dentry; |
2979 | const struct cred *cred = ctx->cred; | 2991 | const struct cred *cred = ctx->cred; |
2980 | struct nfs4_threshold **ctx_th = &ctx->mdsthreshold; | 2992 | struct nfs4_threshold **ctx_th = &ctx->mdsthreshold; |
2981 | fmode_t fmode = ctx->mode & (FMODE_READ|FMODE_WRITE|FMODE_EXEC); | 2993 | fmode_t fmode = _nfs4_ctx_to_openmode(ctx); |
2982 | enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL; | 2994 | enum open_claim_type4 claim = NFS4_OPEN_CLAIM_NULL; |
2983 | struct iattr *sattr = c->sattr; | 2995 | struct iattr *sattr = c->sattr; |
2984 | struct nfs4_label *label = c->label; | 2996 | struct nfs4_label *label = c->label; |
@@ -3024,7 +3036,7 @@ static int _nfs4_do_open(struct inode *dir, | |||
3024 | if (d_really_is_positive(dentry)) | 3036 | if (d_really_is_positive(dentry)) |
3025 | opendata->state = nfs4_get_open_state(d_inode(dentry), sp); | 3037 | opendata->state = nfs4_get_open_state(d_inode(dentry), sp); |
3026 | 3038 | ||
3027 | status = _nfs4_open_and_get_state(opendata, fmode, flags, ctx); | 3039 | status = _nfs4_open_and_get_state(opendata, flags, ctx); |
3028 | if (status != 0) | 3040 | if (status != 0) |
3029 | goto err_free_label; | 3041 | goto err_free_label; |
3030 | state = ctx->state; | 3042 | state = ctx->state; |
@@ -3594,9 +3606,9 @@ static void nfs4_close_context(struct nfs_open_context *ctx, int is_sync) | |||
3594 | if (ctx->state == NULL) | 3606 | if (ctx->state == NULL) |
3595 | return; | 3607 | return; |
3596 | if (is_sync) | 3608 | if (is_sync) |
3597 | nfs4_close_sync(ctx->state, ctx->mode); | 3609 | nfs4_close_sync(ctx->state, _nfs4_ctx_to_openmode(ctx)); |
3598 | else | 3610 | else |
3599 | nfs4_close_state(ctx->state, ctx->mode); | 3611 | nfs4_close_state(ctx->state, _nfs4_ctx_to_openmode(ctx)); |
3600 | } | 3612 | } |
3601 | 3613 | ||
3602 | #define FATTR4_WORD1_NFS40_MASK (2*FATTR4_WORD1_MOUNTED_ON_FILEID - 1UL) | 3614 | #define FATTR4_WORD1_NFS40_MASK (2*FATTR4_WORD1_MOUNTED_ON_FILEID - 1UL) |