diff options
-rw-r--r-- | fs/nfs/dir.c | 7 | ||||
-rw-r--r-- | fs/nfs/inode.c | 61 | ||||
-rw-r--r-- | fs/nfs/nfs4proc.c | 292 | ||||
-rw-r--r-- | fs/nfs/nfs4xdr.c | 154 | ||||
-rw-r--r-- | fs/nfs/super.c | 17 | ||||
-rw-r--r-- | include/linux/nfs_fs.h | 3 | ||||
-rw-r--r-- | include/linux/nfs_fs_sb.h | 5 | ||||
-rw-r--r-- | security/selinux/hooks.c | 4 |
8 files changed, 489 insertions, 54 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index 736b607ac8a8..743d3b524fc5 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -435,6 +435,7 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
435 | struct dentry *alias; | 435 | struct dentry *alias; |
436 | struct inode *dir = parent->d_inode; | 436 | struct inode *dir = parent->d_inode; |
437 | struct inode *inode; | 437 | struct inode *inode; |
438 | int status; | ||
438 | 439 | ||
439 | if (filename.name[0] == '.') { | 440 | if (filename.name[0] == '.') { |
440 | if (filename.len == 1) | 441 | if (filename.len == 1) |
@@ -447,7 +448,9 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry) | |||
447 | dentry = d_lookup(parent, &filename); | 448 | dentry = d_lookup(parent, &filename); |
448 | if (dentry != NULL) { | 449 | if (dentry != NULL) { |
449 | if (nfs_same_file(dentry, entry)) { | 450 | if (nfs_same_file(dentry, entry)) { |
450 | nfs_refresh_inode(dentry->d_inode, entry->fattr); | 451 | status = nfs_refresh_inode(dentry->d_inode, entry->fattr); |
452 | if (!status) | ||
453 | nfs_setsecurity(dentry->d_inode, entry->fattr, entry->label); | ||
451 | goto out; | 454 | goto out; |
452 | } else { | 455 | } else { |
453 | if (d_invalidate(dentry) != 0) | 456 | if (d_invalidate(dentry) != 0) |
@@ -1103,6 +1106,8 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags) | |||
1103 | if ((error = nfs_refresh_inode(inode, fattr)) != 0) | 1106 | if ((error = nfs_refresh_inode(inode, fattr)) != 0) |
1104 | goto out_bad; | 1107 | goto out_bad; |
1105 | 1108 | ||
1109 | nfs_setsecurity(inode, fattr, label); | ||
1110 | |||
1106 | nfs_free_fattr(fattr); | 1111 | nfs_free_fattr(fattr); |
1107 | nfs_free_fhandle(fhandle); | 1112 | nfs_free_fhandle(fhandle); |
1108 | nfs4_label_free(label); | 1113 | nfs4_label_free(label); |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 12e8ad85ae50..f908af672197 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -162,11 +162,19 @@ static void nfs_zap_caches_locked(struct inode *inode) | |||
162 | 162 | ||
163 | memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); | 163 | memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf)); |
164 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { | 164 | if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) { |
165 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | ||
166 | nfs_fscache_invalidate(inode); | 165 | nfs_fscache_invalidate(inode); |
167 | } else { | 166 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR |
168 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE; | 167 | | NFS_INO_INVALID_LABEL |
169 | } | 168 | | NFS_INO_INVALID_DATA |
169 | | NFS_INO_INVALID_ACCESS | ||
170 | | NFS_INO_INVALID_ACL | ||
171 | | NFS_INO_REVAL_PAGECACHE; | ||
172 | } else | ||
173 | nfsi->cache_validity |= NFS_INO_INVALID_ATTR | ||
174 | | NFS_INO_INVALID_LABEL | ||
175 | | NFS_INO_INVALID_ACCESS | ||
176 | | NFS_INO_INVALID_ACL | ||
177 | | NFS_INO_REVAL_PAGECACHE; | ||
170 | } | 178 | } |
171 | 179 | ||
172 | void nfs_zap_caches(struct inode *inode) | 180 | void nfs_zap_caches(struct inode *inode) |
@@ -258,6 +266,32 @@ nfs_init_locked(struct inode *inode, void *opaque) | |||
258 | } | 266 | } |
259 | 267 | ||
260 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | 268 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL |
269 | void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | ||
270 | struct nfs4_label *label) | ||
271 | { | ||
272 | int error; | ||
273 | |||
274 | if (label == NULL) | ||
275 | return; | ||
276 | |||
277 | if (nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL) == 0) | ||
278 | return; | ||
279 | |||
280 | if (NFS_SERVER(inode)->nfs_client->cl_minorversion < 2) | ||
281 | return; | ||
282 | |||
283 | if ((fattr->valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL) && inode->i_security) { | ||
284 | error = security_inode_notifysecctx(inode, label->label, | ||
285 | label->len); | ||
286 | if (error) | ||
287 | printk(KERN_ERR "%s() %s %d " | ||
288 | "security_inode_notifysecctx() %d\n", | ||
289 | __func__, | ||
290 | (char *)label->label, | ||
291 | label->len, error); | ||
292 | } | ||
293 | } | ||
294 | |||
261 | struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) | 295 | struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) |
262 | { | 296 | { |
263 | struct nfs4_label *label = NULL; | 297 | struct nfs4_label *label = NULL; |
@@ -283,7 +317,13 @@ struct nfs4_label *nfs4_label_alloc(struct nfs_server *server, gfp_t flags) | |||
283 | return label; | 317 | return label; |
284 | } | 318 | } |
285 | EXPORT_SYMBOL_GPL(nfs4_label_alloc); | 319 | EXPORT_SYMBOL_GPL(nfs4_label_alloc); |
320 | #else | ||
321 | void inline nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | ||
322 | struct nfs4_label *label) | ||
323 | { | ||
324 | } | ||
286 | #endif | 325 | #endif |
326 | EXPORT_SYMBOL_GPL(nfs_setsecurity); | ||
287 | 327 | ||
288 | /* | 328 | /* |
289 | * This is our front-end to iget that looks up inodes by file handle | 329 | * This is our front-end to iget that looks up inodes by file handle |
@@ -412,6 +452,9 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st | |||
412 | */ | 452 | */ |
413 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); | 453 | inode->i_blocks = nfs_calc_block_size(fattr->du.nfs3.used); |
414 | } | 454 | } |
455 | |||
456 | nfs_setsecurity(inode, fattr, label); | ||
457 | |||
415 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 458 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
416 | nfsi->attrtimeo_timestamp = now; | 459 | nfsi->attrtimeo_timestamp = now; |
417 | nfsi->access_cache = RB_ROOT; | 460 | nfsi->access_cache = RB_ROOT; |
@@ -421,6 +464,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr, st | |||
421 | unlock_new_inode(inode); | 464 | unlock_new_inode(inode); |
422 | } else | 465 | } else |
423 | nfs_refresh_inode(inode, fattr); | 466 | nfs_refresh_inode(inode, fattr); |
467 | nfs_setsecurity(inode, fattr, label); | ||
424 | dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n", | 468 | dprintk("NFS: nfs_fhget(%s/%Ld fh_crc=0x%08x ct=%d)\n", |
425 | inode->i_sb->s_id, | 469 | inode->i_sb->s_id, |
426 | (long long)NFS_FILEID(inode), | 470 | (long long)NFS_FILEID(inode), |
@@ -477,7 +521,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr) | |||
477 | NFS_PROTO(inode)->return_delegation(inode); | 521 | NFS_PROTO(inode)->return_delegation(inode); |
478 | error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); | 522 | error = NFS_PROTO(inode)->setattr(dentry, fattr, attr); |
479 | if (error == 0) | 523 | if (error == 0) |
480 | nfs_refresh_inode(inode, fattr); | 524 | error = nfs_refresh_inode(inode, fattr); |
481 | nfs_free_fattr(fattr); | 525 | nfs_free_fattr(fattr); |
482 | out: | 526 | out: |
483 | return error; | 527 | return error; |
@@ -901,7 +945,8 @@ static int nfs_attribute_cache_expired(struct inode *inode) | |||
901 | */ | 945 | */ |
902 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) | 946 | int nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) |
903 | { | 947 | { |
904 | if (!(NFS_I(inode)->cache_validity & NFS_INO_INVALID_ATTR) | 948 | if (!(NFS_I(inode)->cache_validity & |
949 | (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) | ||
905 | && !nfs_attribute_cache_expired(inode)) | 950 | && !nfs_attribute_cache_expired(inode)) |
906 | return NFS_STALE(inode) ? -ESTALE : 0; | 951 | return NFS_STALE(inode) ? -ESTALE : 0; |
907 | return __nfs_revalidate_inode(server, inode); | 952 | return __nfs_revalidate_inode(server, inode); |
@@ -1281,6 +1326,7 @@ int nfs_post_op_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1281 | spin_lock(&inode->i_lock); | 1326 | spin_lock(&inode->i_lock); |
1282 | status = nfs_post_op_update_inode_locked(inode, fattr); | 1327 | status = nfs_post_op_update_inode_locked(inode, fattr); |
1283 | spin_unlock(&inode->i_lock); | 1328 | spin_unlock(&inode->i_lock); |
1329 | |||
1284 | return status; | 1330 | return status; |
1285 | } | 1331 | } |
1286 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); | 1332 | EXPORT_SYMBOL_GPL(nfs_post_op_update_inode); |
@@ -1521,7 +1567,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1521 | inode->i_blocks = fattr->du.nfs2.blocks; | 1567 | inode->i_blocks = fattr->du.nfs2.blocks; |
1522 | 1568 | ||
1523 | /* Update attrtimeo value if we're out of the unstable period */ | 1569 | /* Update attrtimeo value if we're out of the unstable period */ |
1524 | if (invalid & NFS_INO_INVALID_ATTR) { | 1570 | if (invalid & (NFS_INO_INVALID_ATTR|NFS_INO_INVALID_LABEL)) { |
1525 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); | 1571 | nfs_inc_stats(inode, NFSIOS_ATTRINVALIDATE); |
1526 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); | 1572 | nfsi->attrtimeo = NFS_MINATTRTIMEO(inode); |
1527 | nfsi->attrtimeo_timestamp = now; | 1573 | nfsi->attrtimeo_timestamp = now; |
@@ -1534,6 +1580,7 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1534 | } | 1580 | } |
1535 | } | 1581 | } |
1536 | invalid &= ~NFS_INO_INVALID_ATTR; | 1582 | invalid &= ~NFS_INO_INVALID_ATTR; |
1583 | invalid &= ~NFS_INO_INVALID_LABEL; | ||
1537 | /* Don't invalidate the data if we were to blame */ | 1584 | /* Don't invalidate the data if we were to blame */ |
1538 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | 1585 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) |
1539 | || S_ISLNK(inode->i_mode))) | 1586 | || S_ISLNK(inode->i_mode))) |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index e9488f5e1037..1dc7aec8e946 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -87,6 +87,56 @@ static int nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
87 | static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *); | 87 | static int nfs41_test_stateid(struct nfs_server *, nfs4_stateid *); |
88 | static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *); | 88 | static int nfs41_free_stateid(struct nfs_server *, nfs4_stateid *); |
89 | #endif | 89 | #endif |
90 | |||
91 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
92 | static inline struct nfs4_label * | ||
93 | nfs4_label_init_security(struct inode *dir, struct dentry *dentry, | ||
94 | struct iattr *sattr, struct nfs4_label *label) | ||
95 | { | ||
96 | int err; | ||
97 | |||
98 | if (label == NULL) | ||
99 | return NULL; | ||
100 | |||
101 | if (nfs_server_capable(dir, NFS_CAP_SECURITY_LABEL) == 0) | ||
102 | return NULL; | ||
103 | |||
104 | if (NFS_SERVER(dir)->nfs_client->cl_minorversion < 2) | ||
105 | return NULL; | ||
106 | |||
107 | err = security_dentry_init_security(dentry, sattr->ia_mode, | ||
108 | &dentry->d_name, (void **)&label->label, &label->len); | ||
109 | if (err == 0) | ||
110 | return label; | ||
111 | |||
112 | return NULL; | ||
113 | } | ||
114 | static inline void | ||
115 | nfs4_label_release_security(struct nfs4_label *label) | ||
116 | { | ||
117 | if (label) | ||
118 | security_release_secctx(label->label, label->len); | ||
119 | } | ||
120 | static inline u32 *nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label) | ||
121 | { | ||
122 | if (label) | ||
123 | return server->attr_bitmask; | ||
124 | |||
125 | return server->attr_bitmask_nl; | ||
126 | } | ||
127 | #else | ||
128 | static inline struct nfs4_label * | ||
129 | nfs4_label_init_security(struct inode *dir, struct dentry *dentry, | ||
130 | struct iattr *sattr, struct nfs4_label *l) | ||
131 | { return NULL; } | ||
132 | static inline void | ||
133 | nfs4_label_release_security(struct nfs4_label *label) | ||
134 | { return; } | ||
135 | static inline u32 * | ||
136 | nfs4_bitmask(struct nfs_server *server, struct nfs4_label *label) | ||
137 | { return server->attr_bitmask; } | ||
138 | #endif | ||
139 | |||
90 | /* Prevent leaks of NFSv4 errors into userland */ | 140 | /* Prevent leaks of NFSv4 errors into userland */ |
91 | static int nfs4_map_errors(int err) | 141 | static int nfs4_map_errors(int err) |
92 | { | 142 | { |
@@ -135,7 +185,10 @@ const u32 nfs4_fattr_bitmap[3] = { | |||
135 | | FATTR4_WORD1_SPACE_USED | 185 | | FATTR4_WORD1_SPACE_USED |
136 | | FATTR4_WORD1_TIME_ACCESS | 186 | | FATTR4_WORD1_TIME_ACCESS |
137 | | FATTR4_WORD1_TIME_METADATA | 187 | | FATTR4_WORD1_TIME_METADATA |
138 | | FATTR4_WORD1_TIME_MODIFY | 188 | | FATTR4_WORD1_TIME_MODIFY, |
189 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
190 | FATTR4_WORD2_SECURITY_LABEL | ||
191 | #endif | ||
139 | }; | 192 | }; |
140 | 193 | ||
141 | static const u32 nfs4_pnfs_open_bitmap[3] = { | 194 | static const u32 nfs4_pnfs_open_bitmap[3] = { |
@@ -861,7 +914,7 @@ static struct nfs4_opendata *nfs4_opendata_alloc(struct dentry *dentry, | |||
861 | p->o_arg.id.uniquifier = sp->so_seqid.owner_id; | 914 | p->o_arg.id.uniquifier = sp->so_seqid.owner_id; |
862 | p->o_arg.name = &dentry->d_name; | 915 | p->o_arg.name = &dentry->d_name; |
863 | p->o_arg.server = server; | 916 | p->o_arg.server = server; |
864 | p->o_arg.bitmask = server->attr_bitmask; | 917 | p->o_arg.bitmask = nfs4_bitmask(server, label); |
865 | p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0]; | 918 | p->o_arg.open_bitmap = &nfs4_fattr_bitmap[0]; |
866 | p->o_arg.label = label; | 919 | p->o_arg.label = label; |
867 | p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim); | 920 | p->o_arg.claim = nfs4_map_atomic_open_claim(server, claim); |
@@ -1195,6 +1248,8 @@ _nfs4_opendata_reclaim_to_nfs4_state(struct nfs4_opendata *data) | |||
1195 | if (ret) | 1248 | if (ret) |
1196 | goto err; | 1249 | goto err; |
1197 | 1250 | ||
1251 | nfs_setsecurity(inode, &data->f_attr, data->f_label); | ||
1252 | |||
1198 | if (data->o_res.delegation_type != 0) | 1253 | if (data->o_res.delegation_type != 0) |
1199 | nfs4_opendata_check_deleg(data, state); | 1254 | nfs4_opendata_check_deleg(data, state); |
1200 | update_open_stateid(state, &data->o_res.stateid, NULL, | 1255 | update_open_stateid(state, &data->o_res.stateid, NULL, |
@@ -2063,6 +2118,7 @@ static int _nfs4_do_open(struct inode *dir, | |||
2063 | if (status == 0) { | 2118 | if (status == 0) { |
2064 | nfs_setattr_update_inode(state->inode, sattr); | 2119 | nfs_setattr_update_inode(state->inode, sattr); |
2065 | nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); | 2120 | nfs_post_op_update_inode(state->inode, opendata->o_res.f_attr); |
2121 | nfs_setsecurity(state->inode, opendata->o_res.f_attr, olabel); | ||
2066 | } | 2122 | } |
2067 | } | 2123 | } |
2068 | 2124 | ||
@@ -2181,6 +2237,10 @@ static int _nfs4_do_setattr(struct inode *inode, struct rpc_cred *cred, | |||
2181 | bool truncate; | 2237 | bool truncate; |
2182 | int status; | 2238 | int status; |
2183 | 2239 | ||
2240 | arg.bitmask = nfs4_bitmask(server, ilabel); | ||
2241 | if (ilabel) | ||
2242 | arg.bitmask = nfs4_bitmask(server, olabel); | ||
2243 | |||
2184 | nfs_fattr_init(fattr); | 2244 | nfs_fattr_init(fattr); |
2185 | 2245 | ||
2186 | /* Servers should only apply open mode checks for file size changes */ | 2246 | /* Servers should only apply open mode checks for file size changes */ |
@@ -2462,11 +2522,16 @@ static struct inode * | |||
2462 | nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr) | 2522 | nfs4_atomic_open(struct inode *dir, struct nfs_open_context *ctx, int open_flags, struct iattr *attr) |
2463 | { | 2523 | { |
2464 | struct nfs4_state *state; | 2524 | struct nfs4_state *state; |
2465 | struct nfs4_label *label = NULL; | 2525 | struct nfs4_label l = {0, 0, 0, NULL}, *label = NULL; |
2526 | |||
2527 | label = nfs4_label_init_security(dir, ctx->dentry, attr, &l); | ||
2466 | 2528 | ||
2467 | /* Protect against concurrent sillydeletes */ | 2529 | /* Protect against concurrent sillydeletes */ |
2468 | state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr, label, | 2530 | state = nfs4_do_open(dir, ctx->dentry, ctx->mode, open_flags, attr, label, |
2469 | ctx->cred, &ctx->mdsthreshold); | 2531 | ctx->cred, &ctx->mdsthreshold); |
2532 | |||
2533 | nfs4_label_release_security(label); | ||
2534 | |||
2470 | if (IS_ERR(state)) | 2535 | if (IS_ERR(state)) |
2471 | return ERR_CAST(state); | 2536 | return ERR_CAST(state); |
2472 | ctx->state = state; | 2537 | ctx->state = state; |
@@ -2526,7 +2591,17 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f | |||
2526 | server->caps |= NFS_CAP_CTIME; | 2591 | server->caps |= NFS_CAP_CTIME; |
2527 | if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY) | 2592 | if (res.attr_bitmask[1] & FATTR4_WORD1_TIME_MODIFY) |
2528 | server->caps |= NFS_CAP_MTIME; | 2593 | server->caps |= NFS_CAP_MTIME; |
2594 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
2595 | if (res.attr_bitmask[2] & FATTR4_WORD2_SECURITY_LABEL) | ||
2596 | server->caps |= NFS_CAP_SECURITY_LABEL; | ||
2597 | #endif | ||
2598 | memcpy(server->attr_bitmask_nl, res.attr_bitmask, | ||
2599 | sizeof(server->attr_bitmask)); | ||
2529 | 2600 | ||
2601 | if (server->caps & NFS_CAP_SECURITY_LABEL) { | ||
2602 | server->attr_bitmask_nl[2] &= ~FATTR4_WORD2_SECURITY_LABEL; | ||
2603 | res.attr_bitmask[2] &= ~FATTR4_WORD2_SECURITY_LABEL; | ||
2604 | } | ||
2530 | memcpy(server->cache_consistency_bitmask, res.attr_bitmask, sizeof(server->cache_consistency_bitmask)); | 2605 | memcpy(server->cache_consistency_bitmask, res.attr_bitmask, sizeof(server->cache_consistency_bitmask)); |
2531 | server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE; | 2606 | server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE; |
2532 | server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; | 2607 | server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY; |
@@ -2552,8 +2627,9 @@ int nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *fhandle) | |||
2552 | static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | 2627 | static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, |
2553 | struct nfs_fsinfo *info) | 2628 | struct nfs_fsinfo *info) |
2554 | { | 2629 | { |
2630 | u32 bitmask[3]; | ||
2555 | struct nfs4_lookup_root_arg args = { | 2631 | struct nfs4_lookup_root_arg args = { |
2556 | .bitmask = nfs4_fattr_bitmap, | 2632 | .bitmask = bitmask, |
2557 | }; | 2633 | }; |
2558 | struct nfs4_lookup_res res = { | 2634 | struct nfs4_lookup_res res = { |
2559 | .server = server, | 2635 | .server = server, |
@@ -2566,6 +2642,13 @@ static int _nfs4_lookup_root(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2566 | .rpc_resp = &res, | 2642 | .rpc_resp = &res, |
2567 | }; | 2643 | }; |
2568 | 2644 | ||
2645 | bitmask[0] = nfs4_fattr_bitmap[0]; | ||
2646 | bitmask[1] = nfs4_fattr_bitmap[1]; | ||
2647 | /* | ||
2648 | * Process the label in the upcoming getfattr | ||
2649 | */ | ||
2650 | bitmask[2] = nfs4_fattr_bitmap[2] & ~FATTR4_WORD2_SECURITY_LABEL; | ||
2651 | |||
2569 | nfs_fattr_init(info->fattr); | 2652 | nfs_fattr_init(info->fattr); |
2570 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 2653 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
2571 | } | 2654 | } |
@@ -2773,7 +2856,9 @@ static int _nfs4_proc_getattr(struct nfs_server *server, struct nfs_fh *fhandle, | |||
2773 | .rpc_argp = &args, | 2856 | .rpc_argp = &args, |
2774 | .rpc_resp = &res, | 2857 | .rpc_resp = &res, |
2775 | }; | 2858 | }; |
2776 | 2859 | ||
2860 | args.bitmask = nfs4_bitmask(server, label); | ||
2861 | |||
2777 | nfs_fattr_init(fattr); | 2862 | nfs_fattr_init(fattr); |
2778 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); | 2863 | return nfs4_call_sync(server->client, server, &msg, &args.seq_args, &res.seq_res, 0); |
2779 | } | 2864 | } |
@@ -2847,9 +2932,10 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, | |||
2847 | return PTR_ERR(label); | 2932 | return PTR_ERR(label); |
2848 | 2933 | ||
2849 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, label); | 2934 | status = nfs4_do_setattr(inode, cred, fattr, sattr, state, NULL, label); |
2850 | if (status == 0) | 2935 | if (status == 0) { |
2851 | nfs_setattr_update_inode(inode, sattr); | 2936 | nfs_setattr_update_inode(inode, sattr); |
2852 | 2937 | nfs_setsecurity(inode, fattr, label); | |
2938 | } | ||
2853 | nfs4_label_free(label); | 2939 | nfs4_label_free(label); |
2854 | return status; | 2940 | return status; |
2855 | } | 2941 | } |
@@ -2868,6 +2954,7 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, | |||
2868 | struct nfs4_lookup_res res = { | 2954 | struct nfs4_lookup_res res = { |
2869 | .server = server, | 2955 | .server = server, |
2870 | .fattr = fattr, | 2956 | .fattr = fattr, |
2957 | .label = label, | ||
2871 | .fh = fhandle, | 2958 | .fh = fhandle, |
2872 | }; | 2959 | }; |
2873 | struct rpc_message msg = { | 2960 | struct rpc_message msg = { |
@@ -2876,6 +2963,8 @@ static int _nfs4_proc_lookup(struct rpc_clnt *clnt, struct inode *dir, | |||
2876 | .rpc_resp = &res, | 2963 | .rpc_resp = &res, |
2877 | }; | 2964 | }; |
2878 | 2965 | ||
2966 | args.bitmask = nfs4_bitmask(server, label); | ||
2967 | |||
2879 | nfs_fattr_init(fattr); | 2968 | nfs_fattr_init(fattr); |
2880 | 2969 | ||
2881 | dprintk("NFS call lookup %s\n", name->name); | 2970 | dprintk("NFS call lookup %s\n", name->name); |
@@ -2980,7 +3069,7 @@ static int _nfs4_proc_access(struct inode *inode, struct nfs_access_entry *entry | |||
2980 | .rpc_cred = entry->cred, | 3069 | .rpc_cred = entry->cred, |
2981 | }; | 3070 | }; |
2982 | int mode = entry->mask; | 3071 | int mode = entry->mask; |
2983 | int status; | 3072 | int status = 0; |
2984 | 3073 | ||
2985 | /* | 3074 | /* |
2986 | * Determine which access bits we want to ask for... | 3075 | * Determine which access bits we want to ask for... |
@@ -3085,7 +3174,7 @@ static int | |||
3085 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 3174 | nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
3086 | int flags) | 3175 | int flags) |
3087 | { | 3176 | { |
3088 | struct nfs4_label *ilabel = NULL; | 3177 | struct nfs4_label l, *ilabel = NULL; |
3089 | struct nfs_open_context *ctx; | 3178 | struct nfs_open_context *ctx; |
3090 | struct nfs4_state *state; | 3179 | struct nfs4_state *state; |
3091 | int status = 0; | 3180 | int status = 0; |
@@ -3094,6 +3183,8 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
3094 | if (IS_ERR(ctx)) | 3183 | if (IS_ERR(ctx)) |
3095 | return PTR_ERR(ctx); | 3184 | return PTR_ERR(ctx); |
3096 | 3185 | ||
3186 | ilabel = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
3187 | |||
3097 | sattr->ia_mode &= ~current_umask(); | 3188 | sattr->ia_mode &= ~current_umask(); |
3098 | state = nfs4_do_open(dir, dentry, ctx->mode, | 3189 | state = nfs4_do_open(dir, dentry, ctx->mode, |
3099 | flags, sattr, ilabel, ctx->cred, | 3190 | flags, sattr, ilabel, ctx->cred, |
@@ -3107,6 +3198,7 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
3107 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); | 3198 | nfs_set_verifier(dentry, nfs_save_change_attribute(dir)); |
3108 | ctx->state = state; | 3199 | ctx->state = state; |
3109 | out: | 3200 | out: |
3201 | nfs4_label_release_security(ilabel); | ||
3110 | put_nfs_open_context(ctx); | 3202 | put_nfs_open_context(ctx); |
3111 | return status; | 3203 | return status; |
3112 | } | 3204 | } |
@@ -3155,6 +3247,8 @@ static void nfs4_proc_unlink_setup(struct rpc_message *msg, struct inode *dir) | |||
3155 | res->server = server; | 3247 | res->server = server; |
3156 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; | 3248 | msg->rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_REMOVE]; |
3157 | nfs41_init_sequence(&args->seq_args, &res->seq_res, 1); | 3249 | nfs41_init_sequence(&args->seq_args, &res->seq_res, 1); |
3250 | |||
3251 | nfs_fattr_init(res->dir_attr); | ||
3158 | } | 3252 | } |
3159 | 3253 | ||
3160 | static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) | 3254 | static void nfs4_proc_unlink_rpc_prepare(struct rpc_task *task, struct nfs_unlinkdata *data) |
@@ -3282,11 +3376,14 @@ static int _nfs4_proc_link(struct inode *inode, struct inode *dir, struct qstr * | |||
3282 | status = PTR_ERR(res.label); | 3376 | status = PTR_ERR(res.label); |
3283 | goto out; | 3377 | goto out; |
3284 | } | 3378 | } |
3379 | arg.bitmask = nfs4_bitmask(server, res.label); | ||
3285 | 3380 | ||
3286 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); | 3381 | status = nfs4_call_sync(server->client, server, &msg, &arg.seq_args, &res.seq_res, 1); |
3287 | if (!status) { | 3382 | if (!status) { |
3288 | update_changeattr(dir, &res.cinfo); | 3383 | update_changeattr(dir, &res.cinfo); |
3289 | nfs_post_op_update_inode(inode, res.fattr); | 3384 | status = nfs_post_op_update_inode(inode, res.fattr); |
3385 | if (!status) | ||
3386 | nfs_setsecurity(inode, res.fattr, res.label); | ||
3290 | } | 3387 | } |
3291 | 3388 | ||
3292 | 3389 | ||
@@ -3339,7 +3436,7 @@ static struct nfs4_createdata *nfs4_alloc_createdata(struct inode *dir, | |||
3339 | data->arg.name = name; | 3436 | data->arg.name = name; |
3340 | data->arg.attrs = sattr; | 3437 | data->arg.attrs = sattr; |
3341 | data->arg.ftype = ftype; | 3438 | data->arg.ftype = ftype; |
3342 | data->arg.bitmask = server->attr_bitmask; | 3439 | data->arg.bitmask = nfs4_bitmask(server, data->label); |
3343 | data->res.server = server; | 3440 | data->res.server = server; |
3344 | data->res.fh = &data->fh; | 3441 | data->res.fh = &data->fh; |
3345 | data->res.fattr = &data->fattr; | 3442 | data->res.fattr = &data->fattr; |
@@ -3400,14 +3497,19 @@ static int nfs4_proc_symlink(struct inode *dir, struct dentry *dentry, | |||
3400 | struct page *page, unsigned int len, struct iattr *sattr) | 3497 | struct page *page, unsigned int len, struct iattr *sattr) |
3401 | { | 3498 | { |
3402 | struct nfs4_exception exception = { }; | 3499 | struct nfs4_exception exception = { }; |
3403 | struct nfs4_label *label = NULL; | 3500 | struct nfs4_label l, *label = NULL; |
3404 | int err; | 3501 | int err; |
3502 | |||
3503 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
3504 | |||
3405 | do { | 3505 | do { |
3406 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3506 | err = nfs4_handle_exception(NFS_SERVER(dir), |
3407 | _nfs4_proc_symlink(dir, dentry, page, | 3507 | _nfs4_proc_symlink(dir, dentry, page, |
3408 | len, sattr, label), | 3508 | len, sattr, label), |
3409 | &exception); | 3509 | &exception); |
3410 | } while (exception.retry); | 3510 | } while (exception.retry); |
3511 | |||
3512 | nfs4_label_release_security(label); | ||
3411 | return err; | 3513 | return err; |
3412 | } | 3514 | } |
3413 | 3515 | ||
@@ -3433,15 +3535,19 @@ static int nfs4_proc_mkdir(struct inode *dir, struct dentry *dentry, | |||
3433 | struct iattr *sattr) | 3535 | struct iattr *sattr) |
3434 | { | 3536 | { |
3435 | struct nfs4_exception exception = { }; | 3537 | struct nfs4_exception exception = { }; |
3436 | struct nfs4_label *label = NULL; | 3538 | struct nfs4_label l, *label = NULL; |
3437 | int err; | 3539 | int err; |
3438 | 3540 | ||
3541 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
3542 | |||
3439 | sattr->ia_mode &= ~current_umask(); | 3543 | sattr->ia_mode &= ~current_umask(); |
3440 | do { | 3544 | do { |
3441 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3545 | err = nfs4_handle_exception(NFS_SERVER(dir), |
3442 | _nfs4_proc_mkdir(dir, dentry, sattr, label), | 3546 | _nfs4_proc_mkdir(dir, dentry, sattr, label), |
3443 | &exception); | 3547 | &exception); |
3444 | } while (exception.retry); | 3548 | } while (exception.retry); |
3549 | nfs4_label_release_security(label); | ||
3550 | |||
3445 | return err; | 3551 | return err; |
3446 | } | 3552 | } |
3447 | 3553 | ||
@@ -3499,7 +3605,7 @@ static int nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred, | |||
3499 | } | 3605 | } |
3500 | 3606 | ||
3501 | static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | 3607 | static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, |
3502 | struct iattr *sattr, dev_t rdev) | 3608 | struct iattr *sattr, struct nfs4_label *label, dev_t rdev) |
3503 | { | 3609 | { |
3504 | struct nfs4_createdata *data; | 3610 | struct nfs4_createdata *data; |
3505 | int mode = sattr->ia_mode; | 3611 | int mode = sattr->ia_mode; |
@@ -3525,6 +3631,7 @@ static int _nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
3525 | goto out_free; | 3631 | goto out_free; |
3526 | } | 3632 | } |
3527 | 3633 | ||
3634 | data->arg.label = label; | ||
3528 | status = nfs4_do_create(dir, dentry, data); | 3635 | status = nfs4_do_create(dir, dentry, data); |
3529 | out_free: | 3636 | out_free: |
3530 | nfs4_free_createdata(data); | 3637 | nfs4_free_createdata(data); |
@@ -3536,14 +3643,20 @@ static int nfs4_proc_mknod(struct inode *dir, struct dentry *dentry, | |||
3536 | struct iattr *sattr, dev_t rdev) | 3643 | struct iattr *sattr, dev_t rdev) |
3537 | { | 3644 | { |
3538 | struct nfs4_exception exception = { }; | 3645 | struct nfs4_exception exception = { }; |
3646 | struct nfs4_label l, *label = NULL; | ||
3539 | int err; | 3647 | int err; |
3540 | 3648 | ||
3649 | label = nfs4_label_init_security(dir, dentry, sattr, &l); | ||
3650 | |||
3541 | sattr->ia_mode &= ~current_umask(); | 3651 | sattr->ia_mode &= ~current_umask(); |
3542 | do { | 3652 | do { |
3543 | err = nfs4_handle_exception(NFS_SERVER(dir), | 3653 | err = nfs4_handle_exception(NFS_SERVER(dir), |
3544 | _nfs4_proc_mknod(dir, dentry, sattr, rdev), | 3654 | _nfs4_proc_mknod(dir, dentry, sattr, label, rdev), |
3545 | &exception); | 3655 | &exception); |
3546 | } while (exception.retry); | 3656 | } while (exception.retry); |
3657 | |||
3658 | nfs4_label_release_security(label); | ||
3659 | |||
3547 | return err; | 3660 | return err; |
3548 | } | 3661 | } |
3549 | 3662 | ||
@@ -4270,6 +4383,155 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen | |||
4270 | return err; | 4383 | return err; |
4271 | } | 4384 | } |
4272 | 4385 | ||
4386 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
4387 | static int _nfs4_get_security_label(struct inode *inode, void *buf, | ||
4388 | size_t buflen) | ||
4389 | { | ||
4390 | struct nfs_server *server = NFS_SERVER(inode); | ||
4391 | struct nfs_fattr fattr; | ||
4392 | struct nfs4_label label = {0, 0, buflen, buf}; | ||
4393 | |||
4394 | u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL }; | ||
4395 | struct nfs4_getattr_arg args = { | ||
4396 | .fh = NFS_FH(inode), | ||
4397 | .bitmask = bitmask, | ||
4398 | }; | ||
4399 | struct nfs4_getattr_res res = { | ||
4400 | .fattr = &fattr, | ||
4401 | .label = &label, | ||
4402 | .server = server, | ||
4403 | }; | ||
4404 | struct rpc_message msg = { | ||
4405 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_GETATTR], | ||
4406 | .rpc_argp = &args, | ||
4407 | .rpc_resp = &res, | ||
4408 | }; | ||
4409 | int ret; | ||
4410 | |||
4411 | nfs_fattr_init(&fattr); | ||
4412 | |||
4413 | ret = rpc_call_sync(server->client, &msg, 0); | ||
4414 | if (ret) | ||
4415 | return ret; | ||
4416 | if (!(fattr.valid & NFS_ATTR_FATTR_V4_SECURITY_LABEL)) | ||
4417 | return -ENOENT; | ||
4418 | if (buflen < label.len) | ||
4419 | return -ERANGE; | ||
4420 | return 0; | ||
4421 | } | ||
4422 | |||
4423 | static int nfs4_get_security_label(struct inode *inode, void *buf, | ||
4424 | size_t buflen) | ||
4425 | { | ||
4426 | struct nfs4_exception exception = { }; | ||
4427 | int err; | ||
4428 | |||
4429 | if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) | ||
4430 | return -EOPNOTSUPP; | ||
4431 | |||
4432 | do { | ||
4433 | err = nfs4_handle_exception(NFS_SERVER(inode), | ||
4434 | _nfs4_get_security_label(inode, buf, buflen), | ||
4435 | &exception); | ||
4436 | } while (exception.retry); | ||
4437 | return err; | ||
4438 | } | ||
4439 | |||
4440 | static int _nfs4_do_set_security_label(struct inode *inode, | ||
4441 | struct nfs4_label *ilabel, | ||
4442 | struct nfs_fattr *fattr, | ||
4443 | struct nfs4_label *olabel) | ||
4444 | { | ||
4445 | |||
4446 | struct iattr sattr = {0}; | ||
4447 | struct nfs_server *server = NFS_SERVER(inode); | ||
4448 | const u32 bitmask[3] = { 0, 0, FATTR4_WORD2_SECURITY_LABEL }; | ||
4449 | struct nfs_setattrargs args = { | ||
4450 | .fh = NFS_FH(inode), | ||
4451 | .iap = &sattr, | ||
4452 | .server = server, | ||
4453 | .bitmask = bitmask, | ||
4454 | .label = ilabel, | ||
4455 | }; | ||
4456 | struct nfs_setattrres res = { | ||
4457 | .fattr = fattr, | ||
4458 | .label = olabel, | ||
4459 | .server = server, | ||
4460 | }; | ||
4461 | struct rpc_message msg = { | ||
4462 | .rpc_proc = &nfs4_procedures[NFSPROC4_CLNT_SETATTR], | ||
4463 | .rpc_argp = &args, | ||
4464 | .rpc_resp = &res, | ||
4465 | }; | ||
4466 | int status; | ||
4467 | |||
4468 | nfs4_stateid_copy(&args.stateid, &zero_stateid); | ||
4469 | |||
4470 | status = rpc_call_sync(server->client, &msg, 0); | ||
4471 | if (status) | ||
4472 | dprintk("%s failed: %d\n", __func__, status); | ||
4473 | |||
4474 | return status; | ||
4475 | } | ||
4476 | |||
4477 | static int nfs4_do_set_security_label(struct inode *inode, | ||
4478 | struct nfs4_label *ilabel, | ||
4479 | struct nfs_fattr *fattr, | ||
4480 | struct nfs4_label *olabel) | ||
4481 | { | ||
4482 | struct nfs4_exception exception = { }; | ||
4483 | int err; | ||
4484 | |||
4485 | do { | ||
4486 | err = nfs4_handle_exception(NFS_SERVER(inode), | ||
4487 | _nfs4_do_set_security_label(inode, ilabel, | ||
4488 | fattr, olabel), | ||
4489 | &exception); | ||
4490 | } while (exception.retry); | ||
4491 | return err; | ||
4492 | } | ||
4493 | |||
4494 | static int | ||
4495 | nfs4_set_security_label(struct dentry *dentry, const void *buf, size_t buflen) | ||
4496 | { | ||
4497 | struct nfs4_label ilabel, *olabel = NULL; | ||
4498 | struct nfs_fattr fattr; | ||
4499 | struct rpc_cred *cred; | ||
4500 | struct inode *inode = dentry->d_inode; | ||
4501 | int status; | ||
4502 | |||
4503 | if (!nfs_server_capable(inode, NFS_CAP_SECURITY_LABEL)) | ||
4504 | return -EOPNOTSUPP; | ||
4505 | |||
4506 | nfs_fattr_init(&fattr); | ||
4507 | |||
4508 | ilabel.pi = 0; | ||
4509 | ilabel.lfs = 0; | ||
4510 | ilabel.label = (char *)buf; | ||
4511 | ilabel.len = buflen; | ||
4512 | |||
4513 | cred = rpc_lookup_cred(); | ||
4514 | if (IS_ERR(cred)) | ||
4515 | return PTR_ERR(cred); | ||
4516 | |||
4517 | olabel = nfs4_label_alloc(NFS_SERVER(inode), GFP_KERNEL); | ||
4518 | if (IS_ERR(olabel)) { | ||
4519 | status = -PTR_ERR(olabel); | ||
4520 | goto out; | ||
4521 | } | ||
4522 | |||
4523 | status = nfs4_do_set_security_label(inode, &ilabel, &fattr, olabel); | ||
4524 | if (status == 0) | ||
4525 | nfs_setsecurity(inode, &fattr, olabel); | ||
4526 | |||
4527 | nfs4_label_free(olabel); | ||
4528 | out: | ||
4529 | put_rpccred(cred); | ||
4530 | return status; | ||
4531 | } | ||
4532 | #endif /* CONFIG_NFS_V4_SECURITY_LABEL */ | ||
4533 | |||
4534 | |||
4273 | static int | 4535 | static int |
4274 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) | 4536 | nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state) |
4275 | { | 4537 | { |
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 727cfe080eae..2a3f77e14db6 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c | |||
@@ -102,12 +102,23 @@ static int nfs4_stat_to_errno(int); | |||
102 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) | 102 | #define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2)) |
103 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 103 | #define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
104 | #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) | 104 | #define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ)) |
105 | #ifdef CONFIG_NFS_V4_SECURITY_LABEL | ||
106 | /* PI(4 bytes) + LFS(4 bytes) + 1(for null terminator?) + MAXLABELLEN */ | ||
107 | #define nfs4_label_maxsz (4 + 4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN)) | ||
108 | #define encode_readdir_space 24 | ||
109 | #define encode_readdir_bitmask_sz 3 | ||
110 | #else | ||
111 | #define nfs4_label_maxsz 0 | ||
112 | #define encode_readdir_space 20 | ||
113 | #define encode_readdir_bitmask_sz 2 | ||
114 | #endif | ||
105 | /* We support only one layout type per file system */ | 115 | /* We support only one layout type per file system */ |
106 | #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) | 116 | #define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8) |
107 | /* This is based on getfattr, which uses the most attributes: */ | 117 | /* This is based on getfattr, which uses the most attributes: */ |
108 | #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ | 118 | #define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \ |
109 | 3 + 3 + 3 + nfs4_owner_maxsz + \ | 119 | 3 + 3 + 3 + nfs4_owner_maxsz + \ |
110 | nfs4_group_maxsz + decode_mdsthreshold_maxsz)) | 120 | nfs4_group_maxsz + nfs4_label_maxsz + \ |
121 | decode_mdsthreshold_maxsz)) | ||
111 | #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ | 122 | #define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \ |
112 | nfs4_fattr_value_maxsz) | 123 | nfs4_fattr_value_maxsz) |
113 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) | 124 | #define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz) |
@@ -115,6 +126,7 @@ static int nfs4_stat_to_errno(int); | |||
115 | 1 + 2 + 1 + \ | 126 | 1 + 2 + 1 + \ |
116 | nfs4_owner_maxsz + \ | 127 | nfs4_owner_maxsz + \ |
117 | nfs4_group_maxsz + \ | 128 | nfs4_group_maxsz + \ |
129 | nfs4_label_maxsz + \ | ||
118 | 4 + 4) | 130 | 4 + 4) |
119 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) | 131 | #define encode_savefh_maxsz (op_encode_hdr_maxsz) |
120 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) | 132 | #define decode_savefh_maxsz (op_decode_hdr_maxsz) |
@@ -192,9 +204,11 @@ static int nfs4_stat_to_errno(int); | |||
192 | encode_stateid_maxsz + 3) | 204 | encode_stateid_maxsz + 3) |
193 | #define decode_read_maxsz (op_decode_hdr_maxsz + 2) | 205 | #define decode_read_maxsz (op_decode_hdr_maxsz + 2) |
194 | #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ | 206 | #define encode_readdir_maxsz (op_encode_hdr_maxsz + \ |
195 | 2 + encode_verifier_maxsz + 5) | 207 | 2 + encode_verifier_maxsz + 5 + \ |
208 | nfs4_label_maxsz) | ||
196 | #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ | 209 | #define decode_readdir_maxsz (op_decode_hdr_maxsz + \ |
197 | decode_verifier_maxsz) | 210 | decode_verifier_maxsz + \ |
211 | nfs4_label_maxsz + nfs4_fattr_maxsz) | ||
198 | #define encode_readlink_maxsz (op_encode_hdr_maxsz) | 212 | #define encode_readlink_maxsz (op_encode_hdr_maxsz) |
199 | #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1) | 213 | #define decode_readlink_maxsz (op_decode_hdr_maxsz + 1) |
200 | #define encode_write_maxsz (op_encode_hdr_maxsz + \ | 214 | #define encode_write_maxsz (op_encode_hdr_maxsz + \ |
@@ -968,7 +982,9 @@ static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *ve | |||
968 | encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE); | 982 | encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE); |
969 | } | 983 | } |
970 | 984 | ||
971 | static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server) | 985 | static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, |
986 | const struct nfs4_label *label, | ||
987 | const struct nfs_server *server) | ||
972 | { | 988 | { |
973 | char owner_name[IDMAP_NAMESZ]; | 989 | char owner_name[IDMAP_NAMESZ]; |
974 | char owner_group[IDMAP_NAMESZ]; | 990 | char owner_group[IDMAP_NAMESZ]; |
@@ -1018,6 +1034,8 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
1018 | } | 1034 | } |
1019 | len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); | 1035 | len += 4 + (XDR_QUADLEN(owner_grouplen) << 2); |
1020 | } | 1036 | } |
1037 | if (label) | ||
1038 | len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2); | ||
1021 | if (iap->ia_valid & ATTR_ATIME_SET) | 1039 | if (iap->ia_valid & ATTR_ATIME_SET) |
1022 | len += 16; | 1040 | len += 16; |
1023 | else if (iap->ia_valid & ATTR_ATIME) | 1041 | else if (iap->ia_valid & ATTR_ATIME) |
@@ -1072,6 +1090,13 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const | |||
1072 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; | 1090 | bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET; |
1073 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); | 1091 | *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME); |
1074 | } | 1092 | } |
1093 | if (label) { | ||
1094 | bmval2 |= FATTR4_WORD2_SECURITY_LABEL; | ||
1095 | *p++ = cpu_to_be32(label->lfs); | ||
1096 | *p++ = cpu_to_be32(label->pi); | ||
1097 | *p++ = cpu_to_be32(label->len); | ||
1098 | p = xdr_encode_opaque_fixed(p, label->label, label->len); | ||
1099 | } | ||
1075 | 1100 | ||
1076 | /* | 1101 | /* |
1077 | * Now we backfill the bitmap and the attribute buffer length. | 1102 | * Now we backfill the bitmap and the attribute buffer length. |
@@ -1138,7 +1163,7 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg * | |||
1138 | } | 1163 | } |
1139 | 1164 | ||
1140 | encode_string(xdr, create->name->len, create->name->name); | 1165 | encode_string(xdr, create->name->len, create->name->name); |
1141 | encode_attrs(xdr, create->attrs, create->server); | 1166 | encode_attrs(xdr, create->attrs, create->label, create->server); |
1142 | } | 1167 | } |
1143 | 1168 | ||
1144 | static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) | 1169 | static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr) |
@@ -1371,11 +1396,11 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op | |||
1371 | switch(arg->createmode) { | 1396 | switch(arg->createmode) { |
1372 | case NFS4_CREATE_UNCHECKED: | 1397 | case NFS4_CREATE_UNCHECKED: |
1373 | *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); | 1398 | *p = cpu_to_be32(NFS4_CREATE_UNCHECKED); |
1374 | encode_attrs(xdr, arg->u.attrs, arg->server); | 1399 | encode_attrs(xdr, arg->u.attrs, arg->label, arg->server); |
1375 | break; | 1400 | break; |
1376 | case NFS4_CREATE_GUARDED: | 1401 | case NFS4_CREATE_GUARDED: |
1377 | *p = cpu_to_be32(NFS4_CREATE_GUARDED); | 1402 | *p = cpu_to_be32(NFS4_CREATE_GUARDED); |
1378 | encode_attrs(xdr, arg->u.attrs, arg->server); | 1403 | encode_attrs(xdr, arg->u.attrs, arg->label, arg->server); |
1379 | break; | 1404 | break; |
1380 | case NFS4_CREATE_EXCLUSIVE: | 1405 | case NFS4_CREATE_EXCLUSIVE: |
1381 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); | 1406 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE); |
@@ -1385,7 +1410,7 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op | |||
1385 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); | 1410 | *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1); |
1386 | encode_nfs4_verifier(xdr, &arg->u.verifier); | 1411 | encode_nfs4_verifier(xdr, &arg->u.verifier); |
1387 | dummy.ia_valid = 0; | 1412 | dummy.ia_valid = 0; |
1388 | encode_attrs(xdr, &dummy, arg->server); | 1413 | encode_attrs(xdr, &dummy, arg->label, arg->server); |
1389 | } | 1414 | } |
1390 | } | 1415 | } |
1391 | 1416 | ||
@@ -1536,7 +1561,7 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, | |||
1536 | 1561 | ||
1537 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) | 1562 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) |
1538 | { | 1563 | { |
1539 | uint32_t attrs[2] = { | 1564 | uint32_t attrs[3] = { |
1540 | FATTR4_WORD0_RDATTR_ERROR, | 1565 | FATTR4_WORD0_RDATTR_ERROR, |
1541 | FATTR4_WORD1_MOUNTED_ON_FILEID, | 1566 | FATTR4_WORD1_MOUNTED_ON_FILEID, |
1542 | }; | 1567 | }; |
@@ -1559,20 +1584,26 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg | |||
1559 | encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr); | 1584 | encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr); |
1560 | encode_uint64(xdr, readdir->cookie); | 1585 | encode_uint64(xdr, readdir->cookie); |
1561 | encode_nfs4_verifier(xdr, &readdir->verifier); | 1586 | encode_nfs4_verifier(xdr, &readdir->verifier); |
1562 | p = reserve_space(xdr, 20); | 1587 | p = reserve_space(xdr, encode_readdir_space); |
1563 | *p++ = cpu_to_be32(dircount); | 1588 | *p++ = cpu_to_be32(dircount); |
1564 | *p++ = cpu_to_be32(readdir->count); | 1589 | *p++ = cpu_to_be32(readdir->count); |
1565 | *p++ = cpu_to_be32(2); | 1590 | *p++ = cpu_to_be32(encode_readdir_bitmask_sz); |
1566 | |||
1567 | *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); | 1591 | *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); |
1568 | *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); | 1592 | *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); |
1593 | if (encode_readdir_bitmask_sz > 2) { | ||
1594 | if (hdr->minorversion > 1) | ||
1595 | attrs[2] |= FATTR4_WORD2_SECURITY_LABEL; | ||
1596 | p++, *p++ = cpu_to_be32(attrs[2] & readdir->bitmask[2]); | ||
1597 | } | ||
1569 | memcpy(verf, readdir->verifier.data, sizeof(verf)); | 1598 | memcpy(verf, readdir->verifier.data, sizeof(verf)); |
1570 | dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n", | 1599 | |
1600 | dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x\n", | ||
1571 | __func__, | 1601 | __func__, |
1572 | (unsigned long long)readdir->cookie, | 1602 | (unsigned long long)readdir->cookie, |
1573 | verf[0], verf[1], | 1603 | verf[0], verf[1], |
1574 | attrs[0] & readdir->bitmask[0], | 1604 | attrs[0] & readdir->bitmask[0], |
1575 | attrs[1] & readdir->bitmask[1]); | 1605 | attrs[1] & readdir->bitmask[1], |
1606 | attrs[2] & readdir->bitmask[2]); | ||
1576 | } | 1607 | } |
1577 | 1608 | ||
1578 | static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) | 1609 | static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr) |
@@ -1631,7 +1662,7 @@ static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs | |||
1631 | { | 1662 | { |
1632 | encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr); | 1663 | encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr); |
1633 | encode_nfs4_stateid(xdr, &arg->stateid); | 1664 | encode_nfs4_stateid(xdr, &arg->stateid); |
1634 | encode_attrs(xdr, arg->iap, server); | 1665 | encode_attrs(xdr, arg->iap, arg->label, server); |
1635 | } | 1666 | } |
1636 | 1667 | ||
1637 | static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) | 1668 | static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr) |
@@ -4042,6 +4073,56 @@ static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4042 | return status; | 4073 | return status; |
4043 | } | 4074 | } |
4044 | 4075 | ||
4076 | static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap, | ||
4077 | struct nfs4_label *label) | ||
4078 | { | ||
4079 | uint32_t pi = 0; | ||
4080 | uint32_t lfs = 0; | ||
4081 | __u32 len; | ||
4082 | __be32 *p; | ||
4083 | int status = 0; | ||
4084 | |||
4085 | if (unlikely(bitmap[2] & (FATTR4_WORD2_SECURITY_LABEL - 1U))) | ||
4086 | return -EIO; | ||
4087 | if (likely(bitmap[2] & FATTR4_WORD2_SECURITY_LABEL)) { | ||
4088 | p = xdr_inline_decode(xdr, 4); | ||
4089 | if (unlikely(!p)) | ||
4090 | goto out_overflow; | ||
4091 | lfs = be32_to_cpup(p++); | ||
4092 | p = xdr_inline_decode(xdr, 4); | ||
4093 | if (unlikely(!p)) | ||
4094 | goto out_overflow; | ||
4095 | pi = be32_to_cpup(p++); | ||
4096 | p = xdr_inline_decode(xdr, 4); | ||
4097 | if (unlikely(!p)) | ||
4098 | goto out_overflow; | ||
4099 | len = be32_to_cpup(p++); | ||
4100 | p = xdr_inline_decode(xdr, len); | ||
4101 | if (unlikely(!p)) | ||
4102 | goto out_overflow; | ||
4103 | if (len < NFS4_MAXLABELLEN) { | ||
4104 | if (label) { | ||
4105 | memcpy(label->label, p, len); | ||
4106 | label->len = len; | ||
4107 | label->pi = pi; | ||
4108 | label->lfs = lfs; | ||
4109 | status = NFS_ATTR_FATTR_V4_SECURITY_LABEL; | ||
4110 | } | ||
4111 | bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL; | ||
4112 | } else | ||
4113 | printk(KERN_WARNING "%s: label too long (%u)!\n", | ||
4114 | __func__, len); | ||
4115 | } | ||
4116 | if (label && label->label) | ||
4117 | dprintk("%s: label=%s, len=%d, PI=%d, LFS=%d\n", __func__, | ||
4118 | (char *)label->label, label->len, label->pi, label->lfs); | ||
4119 | return status; | ||
4120 | |||
4121 | out_overflow: | ||
4122 | print_overflow_msg(__func__, xdr); | ||
4123 | return -EIO; | ||
4124 | } | ||
4125 | |||
4045 | static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) | 4126 | static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time) |
4046 | { | 4127 | { |
4047 | int status = 0; | 4128 | int status = 0; |
@@ -4384,7 +4465,7 @@ out_overflow: | |||
4384 | 4465 | ||
4385 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | 4466 | static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, |
4386 | struct nfs_fattr *fattr, struct nfs_fh *fh, | 4467 | struct nfs_fattr *fattr, struct nfs_fh *fh, |
4387 | struct nfs4_fs_locations *fs_loc, | 4468 | struct nfs4_fs_locations *fs_loc, struct nfs4_label *label, |
4388 | const struct nfs_server *server) | 4469 | const struct nfs_server *server) |
4389 | { | 4470 | { |
4390 | int status; | 4471 | int status; |
@@ -4492,6 +4573,13 @@ static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap, | |||
4492 | if (status < 0) | 4573 | if (status < 0) |
4493 | goto xdr_error; | 4574 | goto xdr_error; |
4494 | 4575 | ||
4576 | if (label) { | ||
4577 | status = decode_attr_security_label(xdr, bitmap, label); | ||
4578 | if (status < 0) | ||
4579 | goto xdr_error; | ||
4580 | fattr->valid |= status; | ||
4581 | } | ||
4582 | |||
4495 | xdr_error: | 4583 | xdr_error: |
4496 | dprintk("%s: xdr returned %d\n", __func__, -status); | 4584 | dprintk("%s: xdr returned %d\n", __func__, -status); |
4497 | return status; | 4585 | return status; |
@@ -4499,7 +4587,7 @@ xdr_error: | |||
4499 | 4587 | ||
4500 | static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, | 4588 | static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr, |
4501 | struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, | 4589 | struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc, |
4502 | const struct nfs_server *server) | 4590 | struct nfs4_label *label, const struct nfs_server *server) |
4503 | { | 4591 | { |
4504 | unsigned int savep; | 4592 | unsigned int savep; |
4505 | uint32_t attrlen, | 4593 | uint32_t attrlen, |
@@ -4518,7 +4606,8 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat | |||
4518 | if (status < 0) | 4606 | if (status < 0) |
4519 | goto xdr_error; | 4607 | goto xdr_error; |
4520 | 4608 | ||
4521 | status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, server); | 4609 | status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, |
4610 | label, server); | ||
4522 | if (status < 0) | 4611 | if (status < 0) |
4523 | goto xdr_error; | 4612 | goto xdr_error; |
4524 | 4613 | ||
@@ -4528,10 +4617,16 @@ xdr_error: | |||
4528 | return status; | 4617 | return status; |
4529 | } | 4618 | } |
4530 | 4619 | ||
4620 | static int decode_getfattr_label(struct xdr_stream *xdr, struct nfs_fattr *fattr, | ||
4621 | struct nfs4_label *label, const struct nfs_server *server) | ||
4622 | { | ||
4623 | return decode_getfattr_generic(xdr, fattr, NULL, NULL, label, server); | ||
4624 | } | ||
4625 | |||
4531 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, | 4626 | static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, |
4532 | const struct nfs_server *server) | 4627 | const struct nfs_server *server) |
4533 | { | 4628 | { |
4534 | return decode_getfattr_generic(xdr, fattr, NULL, NULL, server); | 4629 | return decode_getfattr_generic(xdr, fattr, NULL, NULL, NULL, server); |
4535 | } | 4630 | } |
4536 | 4631 | ||
4537 | /* | 4632 | /* |
@@ -5923,7 +6018,7 @@ static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
5923 | status = decode_getfh(xdr, res->fh); | 6018 | status = decode_getfh(xdr, res->fh); |
5924 | if (status) | 6019 | if (status) |
5925 | goto out; | 6020 | goto out; |
5926 | status = decode_getfattr(xdr, res->fattr, res->server); | 6021 | status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
5927 | out: | 6022 | out: |
5928 | return status; | 6023 | return status; |
5929 | } | 6024 | } |
@@ -5949,7 +6044,8 @@ static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, | |||
5949 | goto out; | 6044 | goto out; |
5950 | status = decode_getfh(xdr, res->fh); | 6045 | status = decode_getfh(xdr, res->fh); |
5951 | if (status == 0) | 6046 | if (status == 0) |
5952 | status = decode_getfattr(xdr, res->fattr, res->server); | 6047 | status = decode_getfattr_label(xdr, res->fattr, |
6048 | res->label, res->server); | ||
5953 | out: | 6049 | out: |
5954 | return status; | 6050 | return status; |
5955 | } | 6051 | } |
@@ -6040,7 +6136,7 @@ static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6040 | status = decode_restorefh(xdr); | 6136 | status = decode_restorefh(xdr); |
6041 | if (status) | 6137 | if (status) |
6042 | goto out; | 6138 | goto out; |
6043 | decode_getfattr(xdr, res->fattr, res->server); | 6139 | decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
6044 | out: | 6140 | out: |
6045 | return status; | 6141 | return status; |
6046 | } | 6142 | } |
@@ -6069,7 +6165,7 @@ static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6069 | status = decode_getfh(xdr, res->fh); | 6165 | status = decode_getfh(xdr, res->fh); |
6070 | if (status) | 6166 | if (status) |
6071 | goto out; | 6167 | goto out; |
6072 | decode_getfattr(xdr, res->fattr, res->server); | 6168 | decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
6073 | out: | 6169 | out: |
6074 | return status; | 6170 | return status; |
6075 | } | 6171 | } |
@@ -6101,7 +6197,7 @@ static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6101 | status = decode_putfh(xdr); | 6197 | status = decode_putfh(xdr); |
6102 | if (status) | 6198 | if (status) |
6103 | goto out; | 6199 | goto out; |
6104 | status = decode_getfattr(xdr, res->fattr, res->server); | 6200 | status = decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
6105 | out: | 6201 | out: |
6106 | return status; | 6202 | return status; |
6107 | } | 6203 | } |
@@ -6234,7 +6330,7 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr, | |||
6234 | goto out; | 6330 | goto out; |
6235 | if (res->access_request) | 6331 | if (res->access_request) |
6236 | decode_access(xdr, &res->access_supported, &res->access_result); | 6332 | decode_access(xdr, &res->access_supported, &res->access_result); |
6237 | decode_getfattr(xdr, res->f_attr, res->server); | 6333 | decode_getfattr_label(xdr, res->f_attr, res->f_label, res->server); |
6238 | out: | 6334 | out: |
6239 | return status; | 6335 | return status; |
6240 | } | 6336 | } |
@@ -6311,7 +6407,7 @@ static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, | |||
6311 | status = decode_setattr(xdr); | 6407 | status = decode_setattr(xdr); |
6312 | if (status) | 6408 | if (status) |
6313 | goto out; | 6409 | goto out; |
6314 | decode_getfattr(xdr, res->fattr, res->server); | 6410 | decode_getfattr_label(xdr, res->fattr, res->label, res->server); |
6315 | out: | 6411 | out: |
6316 | return status; | 6412 | return status; |
6317 | } | 6413 | } |
@@ -6700,7 +6796,7 @@ static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, | |||
6700 | xdr_enter_page(xdr, PAGE_SIZE); | 6796 | xdr_enter_page(xdr, PAGE_SIZE); |
6701 | status = decode_getfattr_generic(xdr, &res->fs_locations->fattr, | 6797 | status = decode_getfattr_generic(xdr, &res->fs_locations->fattr, |
6702 | NULL, res->fs_locations, | 6798 | NULL, res->fs_locations, |
6703 | res->fs_locations->server); | 6799 | NULL, res->fs_locations->server); |
6704 | out: | 6800 | out: |
6705 | return status; | 6801 | return status; |
6706 | } | 6802 | } |
@@ -7113,7 +7209,7 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, | |||
7113 | goto out_overflow; | 7209 | goto out_overflow; |
7114 | 7210 | ||
7115 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, | 7211 | if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, |
7116 | NULL, entry->server) < 0) | 7212 | NULL, entry->label, entry->server) < 0) |
7117 | goto out_overflow; | 7213 | goto out_overflow; |
7118 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) | 7214 | if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID) |
7119 | entry->ino = entry->fattr->mounted_on_fileid; | 7215 | entry->ino = entry->fattr->mounted_on_fileid; |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index b30c003b47d1..76e1ee5d03ed 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -2417,8 +2417,21 @@ static int nfs_bdi_register(struct nfs_server *server) | |||
2417 | int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, | 2417 | int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, |
2418 | struct nfs_mount_info *mount_info) | 2418 | struct nfs_mount_info *mount_info) |
2419 | { | 2419 | { |
2420 | return security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts, | 2420 | int error; |
2421 | 0, NULL); | 2421 | unsigned long kflags = 0, kflags_out = 0; |
2422 | if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL) | ||
2423 | kflags |= SECURITY_LSM_NATIVE_LABELS; | ||
2424 | |||
2425 | error = security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts, | ||
2426 | kflags, &kflags_out); | ||
2427 | if (error) | ||
2428 | goto err; | ||
2429 | |||
2430 | if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL && | ||
2431 | !(kflags_out & SECURITY_LSM_NATIVE_LABELS)) | ||
2432 | NFS_SB(s)->caps &= ~NFS_CAP_SECURITY_LABEL; | ||
2433 | err: | ||
2434 | return error; | ||
2422 | } | 2435 | } |
2423 | EXPORT_SYMBOL_GPL(nfs_set_sb_security); | 2436 | EXPORT_SYMBOL_GPL(nfs_set_sb_security); |
2424 | 2437 | ||
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 3489015950b4..d4b003d9e78d 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h | |||
@@ -207,6 +207,7 @@ struct nfs_inode { | |||
207 | #define NFS_INO_INVALID_ACL 0x0010 /* cached acls are invalid */ | 207 | #define NFS_INO_INVALID_ACL 0x0010 /* cached acls are invalid */ |
208 | #define NFS_INO_REVAL_PAGECACHE 0x0020 /* must revalidate pagecache */ | 208 | #define NFS_INO_REVAL_PAGECACHE 0x0020 /* must revalidate pagecache */ |
209 | #define NFS_INO_REVAL_FORCED 0x0040 /* force revalidation ignoring a delegation */ | 209 | #define NFS_INO_REVAL_FORCED 0x0040 /* force revalidation ignoring a delegation */ |
210 | #define NFS_INO_INVALID_LABEL 0x0080 /* cached label is invalid */ | ||
210 | 211 | ||
211 | /* | 212 | /* |
212 | * Bit offsets in flags field | 213 | * Bit offsets in flags field |
@@ -352,6 +353,8 @@ extern int __nfs_revalidate_inode(struct nfs_server *, struct inode *); | |||
352 | extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); | 353 | extern int nfs_revalidate_mapping(struct inode *inode, struct address_space *mapping); |
353 | extern int nfs_setattr(struct dentry *, struct iattr *); | 354 | extern int nfs_setattr(struct dentry *, struct iattr *); |
354 | extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr); | 355 | extern void nfs_setattr_update_inode(struct inode *inode, struct iattr *attr); |
356 | extern void nfs_setsecurity(struct inode *inode, struct nfs_fattr *fattr, | ||
357 | struct nfs4_label *label); | ||
355 | extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); | 358 | extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); |
356 | extern void put_nfs_open_context(struct nfs_open_context *ctx); | 359 | extern void put_nfs_open_context(struct nfs_open_context *ctx); |
357 | extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode); | 360 | extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, fmode_t mode); |
diff --git a/include/linux/nfs_fs_sb.h b/include/linux/nfs_fs_sb.h index d4348ab1e0e4..d2212432c456 100644 --- a/include/linux/nfs_fs_sb.h +++ b/include/linux/nfs_fs_sb.h | |||
@@ -146,6 +146,11 @@ struct nfs_server { | |||
146 | u32 attr_bitmask[3];/* V4 bitmask representing the set | 146 | u32 attr_bitmask[3];/* V4 bitmask representing the set |
147 | of attributes supported on this | 147 | of attributes supported on this |
148 | filesystem */ | 148 | filesystem */ |
149 | u32 attr_bitmask_nl[3]; | ||
150 | /* V4 bitmask representing the | ||
151 | set of attributes supported | ||
152 | on this filesystem excluding | ||
153 | the label support bit. */ | ||
149 | u32 cache_consistency_bitmask[3]; | 154 | u32 cache_consistency_bitmask[3]; |
150 | /* V4 bitmask representing the subset | 155 | /* V4 bitmask representing the subset |
151 | of change attribute, size, ctime | 156 | of change attribute, size, ctime |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6149633ff715..9f8e9b2e717a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -2908,7 +2908,10 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
2908 | return; | 2908 | return; |
2909 | } | 2909 | } |
2910 | 2910 | ||
2911 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
2911 | isec->sid = newsid; | 2912 | isec->sid = newsid; |
2913 | isec->initialized = 1; | ||
2914 | |||
2912 | return; | 2915 | return; |
2913 | } | 2916 | } |
2914 | 2917 | ||
@@ -2996,6 +2999,7 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name, | |||
2996 | if (rc) | 2999 | if (rc) |
2997 | return rc; | 3000 | return rc; |
2998 | 3001 | ||
3002 | isec->sclass = inode_mode_to_security_class(inode->i_mode); | ||
2999 | isec->sid = newsid; | 3003 | isec->sid = newsid; |
3000 | isec->initialized = 1; | 3004 | isec->initialized = 1; |
3001 | return 0; | 3005 | return 0; |