diff options
author | David S. Miller <davem@davemloft.net> | 2008-03-18 02:44:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-03-18 02:44:31 -0400 |
commit | 2f633928cbba8a5858bb39b11e7219a41b0fbef5 (patch) | |
tree | 9a82f4b7f2c3afe4b0208d8e44ea61bae90a7d22 /fs/nfs | |
parent | 5e226e4d9016daee170699f8a4188a5505021756 (diff) | |
parent | bde4f8fa8db2abd5ac9c542d76012d0fedab050f (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/dir.c | 2 | ||||
-rw-r--r-- | fs/nfs/inode.c | 6 | ||||
-rw-r--r-- | fs/nfs/internal.h | 3 | ||||
-rw-r--r-- | fs/nfs/super.c | 64 | ||||
-rw-r--r-- | fs/nfs/write.c | 2 |
5 files changed, 72 insertions, 5 deletions
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index ae04892a5e5d..6cea7479c5b4 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c | |||
@@ -710,6 +710,8 @@ int nfs_lookup_verify_inode(struct inode *inode, struct nameidata *nd) | |||
710 | { | 710 | { |
711 | struct nfs_server *server = NFS_SERVER(inode); | 711 | struct nfs_server *server = NFS_SERVER(inode); |
712 | 712 | ||
713 | if (test_bit(NFS_INO_MOUNTPOINT, &NFS_I(inode)->flags)) | ||
714 | return 0; | ||
713 | if (nd != NULL) { | 715 | if (nd != NULL) { |
714 | /* VFS wants an on-the-wire revalidation */ | 716 | /* VFS wants an on-the-wire revalidation */ |
715 | if (nd->flags & LOOKUP_REVAL) | 717 | if (nd->flags & LOOKUP_REVAL) |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 966a8850aa30..a4c7cf2bff3a 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -299,6 +299,7 @@ nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) | |||
299 | else | 299 | else |
300 | inode->i_op = &nfs_mountpoint_inode_operations; | 300 | inode->i_op = &nfs_mountpoint_inode_operations; |
301 | inode->i_fop = NULL; | 301 | inode->i_fop = NULL; |
302 | set_bit(NFS_INO_MOUNTPOINT, &nfsi->flags); | ||
302 | } | 303 | } |
303 | } else if (S_ISLNK(inode->i_mode)) | 304 | } else if (S_ISLNK(inode->i_mode)) |
304 | inode->i_op = &nfs_symlink_inode_operations; | 305 | inode->i_op = &nfs_symlink_inode_operations; |
@@ -1003,8 +1004,9 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr) | |||
1003 | 1004 | ||
1004 | server = NFS_SERVER(inode); | 1005 | server = NFS_SERVER(inode); |
1005 | /* Update the fsid? */ | 1006 | /* Update the fsid? */ |
1006 | if (S_ISDIR(inode->i_mode) | 1007 | if (S_ISDIR(inode->i_mode) && |
1007 | && !nfs_fsid_equal(&server->fsid, &fattr->fsid)) | 1008 | !nfs_fsid_equal(&server->fsid, &fattr->fsid) && |
1009 | !test_bit(NFS_INO_MOUNTPOINT, &nfsi->flags)) | ||
1008 | server->fsid = fattr->fsid; | 1010 | server->fsid = fattr->fsid; |
1009 | 1011 | ||
1010 | /* | 1012 | /* |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 0f5619611b8d..931992763e68 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -3,6 +3,7 @@ | |||
3 | */ | 3 | */ |
4 | 4 | ||
5 | #include <linux/mount.h> | 5 | #include <linux/mount.h> |
6 | #include <linux/security.h> | ||
6 | 7 | ||
7 | struct nfs_string; | 8 | struct nfs_string; |
8 | 9 | ||
@@ -57,6 +58,8 @@ struct nfs_parsed_mount_data { | |||
57 | char *export_path; | 58 | char *export_path; |
58 | int protocol; | 59 | int protocol; |
59 | } nfs_server; | 60 | } nfs_server; |
61 | |||
62 | struct security_mnt_opts lsm_opts; | ||
60 | }; | 63 | }; |
61 | 64 | ||
62 | /* client.c */ | 65 | /* client.c */ |
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index bdcf6d3ef62f..dd4dfcd632ec 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -684,8 +684,9 @@ static void nfs_parse_server_address(char *value, | |||
684 | static int nfs_parse_mount_options(char *raw, | 684 | static int nfs_parse_mount_options(char *raw, |
685 | struct nfs_parsed_mount_data *mnt) | 685 | struct nfs_parsed_mount_data *mnt) |
686 | { | 686 | { |
687 | char *p, *string; | 687 | char *p, *string, *secdata; |
688 | unsigned short port = 0; | 688 | unsigned short port = 0; |
689 | int rc; | ||
689 | 690 | ||
690 | if (!raw) { | 691 | if (!raw) { |
691 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); | 692 | dfprintk(MOUNT, "NFS: mount options string was NULL.\n"); |
@@ -693,6 +694,20 @@ static int nfs_parse_mount_options(char *raw, | |||
693 | } | 694 | } |
694 | dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw); | 695 | dfprintk(MOUNT, "NFS: nfs mount opts='%s'\n", raw); |
695 | 696 | ||
697 | secdata = alloc_secdata(); | ||
698 | if (!secdata) | ||
699 | goto out_nomem; | ||
700 | |||
701 | rc = security_sb_copy_data(raw, secdata); | ||
702 | if (rc) | ||
703 | goto out_security_failure; | ||
704 | |||
705 | rc = security_sb_parse_opts_str(secdata, &mnt->lsm_opts); | ||
706 | if (rc) | ||
707 | goto out_security_failure; | ||
708 | |||
709 | free_secdata(secdata); | ||
710 | |||
696 | while ((p = strsep(&raw, ",")) != NULL) { | 711 | while ((p = strsep(&raw, ",")) != NULL) { |
697 | substring_t args[MAX_OPT_ARGS]; | 712 | substring_t args[MAX_OPT_ARGS]; |
698 | int option, token; | 713 | int option, token; |
@@ -1042,7 +1057,10 @@ static int nfs_parse_mount_options(char *raw, | |||
1042 | out_nomem: | 1057 | out_nomem: |
1043 | printk(KERN_INFO "NFS: not enough memory to parse option\n"); | 1058 | printk(KERN_INFO "NFS: not enough memory to parse option\n"); |
1044 | return 0; | 1059 | return 0; |
1045 | 1060 | out_security_failure: | |
1061 | free_secdata(secdata); | ||
1062 | printk(KERN_INFO "NFS: security options invalid: %d\n", rc); | ||
1063 | return 0; | ||
1046 | out_unrec_vers: | 1064 | out_unrec_vers: |
1047 | printk(KERN_INFO "NFS: unrecognized NFS version number\n"); | 1065 | printk(KERN_INFO "NFS: unrecognized NFS version number\n"); |
1048 | return 0; | 1066 | return 0; |
@@ -1214,6 +1232,33 @@ static int nfs_validate_mount_data(void *options, | |||
1214 | args->namlen = data->namlen; | 1232 | args->namlen = data->namlen; |
1215 | args->bsize = data->bsize; | 1233 | args->bsize = data->bsize; |
1216 | args->auth_flavors[0] = data->pseudoflavor; | 1234 | args->auth_flavors[0] = data->pseudoflavor; |
1235 | |||
1236 | /* | ||
1237 | * The legacy version 6 binary mount data from userspace has a | ||
1238 | * field used only to transport selinux information into the | ||
1239 | * the kernel. To continue to support that functionality we | ||
1240 | * have a touch of selinux knowledge here in the NFS code. The | ||
1241 | * userspace code converted context=blah to just blah so we are | ||
1242 | * converting back to the full string selinux understands. | ||
1243 | */ | ||
1244 | if (data->context[0]){ | ||
1245 | #ifdef CONFIG_SECURITY_SELINUX | ||
1246 | int rc; | ||
1247 | char *opts_str = kmalloc(sizeof(data->context) + 8, GFP_KERNEL); | ||
1248 | if (!opts_str) | ||
1249 | return -ENOMEM; | ||
1250 | strcpy(opts_str, "context="); | ||
1251 | data->context[NFS_MAX_CONTEXT_LEN] = '\0'; | ||
1252 | strcat(opts_str, &data->context[0]); | ||
1253 | rc = security_sb_parse_opts_str(opts_str, &args->lsm_opts); | ||
1254 | kfree(opts_str); | ||
1255 | if (rc) | ||
1256 | return rc; | ||
1257 | #else | ||
1258 | return -EINVAL; | ||
1259 | #endif | ||
1260 | } | ||
1261 | |||
1217 | break; | 1262 | break; |
1218 | default: { | 1263 | default: { |
1219 | unsigned int len; | 1264 | unsigned int len; |
@@ -1476,6 +1521,8 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1476 | }; | 1521 | }; |
1477 | int error; | 1522 | int error; |
1478 | 1523 | ||
1524 | security_init_mnt_opts(&data.lsm_opts); | ||
1525 | |||
1479 | /* Validate the mount data */ | 1526 | /* Validate the mount data */ |
1480 | error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name); | 1527 | error = nfs_validate_mount_data(raw_data, &data, &mntfh, dev_name); |
1481 | if (error < 0) | 1528 | if (error < 0) |
@@ -1515,6 +1562,10 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1515 | goto error_splat_super; | 1562 | goto error_splat_super; |
1516 | } | 1563 | } |
1517 | 1564 | ||
1565 | error = security_sb_set_mnt_opts(s, &data.lsm_opts); | ||
1566 | if (error) | ||
1567 | goto error_splat_root; | ||
1568 | |||
1518 | s->s_flags |= MS_ACTIVE; | 1569 | s->s_flags |= MS_ACTIVE; |
1519 | mnt->mnt_sb = s; | 1570 | mnt->mnt_sb = s; |
1520 | mnt->mnt_root = mntroot; | 1571 | mnt->mnt_root = mntroot; |
@@ -1523,12 +1574,15 @@ static int nfs_get_sb(struct file_system_type *fs_type, | |||
1523 | out: | 1574 | out: |
1524 | kfree(data.nfs_server.hostname); | 1575 | kfree(data.nfs_server.hostname); |
1525 | kfree(data.mount_server.hostname); | 1576 | kfree(data.mount_server.hostname); |
1577 | security_free_mnt_opts(&data.lsm_opts); | ||
1526 | return error; | 1578 | return error; |
1527 | 1579 | ||
1528 | out_err_nosb: | 1580 | out_err_nosb: |
1529 | nfs_free_server(server); | 1581 | nfs_free_server(server); |
1530 | goto out; | 1582 | goto out; |
1531 | 1583 | ||
1584 | error_splat_root: | ||
1585 | dput(mntroot); | ||
1532 | error_splat_super: | 1586 | error_splat_super: |
1533 | up_write(&s->s_umount); | 1587 | up_write(&s->s_umount); |
1534 | deactivate_super(s); | 1588 | deactivate_super(s); |
@@ -1608,6 +1662,9 @@ static int nfs_xdev_get_sb(struct file_system_type *fs_type, int flags, | |||
1608 | mnt->mnt_sb = s; | 1662 | mnt->mnt_sb = s; |
1609 | mnt->mnt_root = mntroot; | 1663 | mnt->mnt_root = mntroot; |
1610 | 1664 | ||
1665 | /* clone any lsm security options from the parent to the new sb */ | ||
1666 | security_sb_clone_mnt_opts(data->sb, s); | ||
1667 | |||
1611 | dprintk("<-- nfs_xdev_get_sb() = 0\n"); | 1668 | dprintk("<-- nfs_xdev_get_sb() = 0\n"); |
1612 | return 0; | 1669 | return 0; |
1613 | 1670 | ||
@@ -1850,6 +1907,8 @@ static int nfs4_get_sb(struct file_system_type *fs_type, | |||
1850 | }; | 1907 | }; |
1851 | int error; | 1908 | int error; |
1852 | 1909 | ||
1910 | security_init_mnt_opts(&data.lsm_opts); | ||
1911 | |||
1853 | /* Validate the mount data */ | 1912 | /* Validate the mount data */ |
1854 | error = nfs4_validate_mount_data(raw_data, &data, dev_name); | 1913 | error = nfs4_validate_mount_data(raw_data, &data, dev_name); |
1855 | if (error < 0) | 1914 | if (error < 0) |
@@ -1898,6 +1957,7 @@ out: | |||
1898 | kfree(data.client_address); | 1957 | kfree(data.client_address); |
1899 | kfree(data.nfs_server.export_path); | 1958 | kfree(data.nfs_server.export_path); |
1900 | kfree(data.nfs_server.hostname); | 1959 | kfree(data.nfs_server.hostname); |
1960 | security_free_mnt_opts(&data.lsm_opts); | ||
1901 | return error; | 1961 | return error; |
1902 | 1962 | ||
1903 | out_free: | 1963 | out_free: |
diff --git a/fs/nfs/write.c b/fs/nfs/write.c index f55c437124a2..80c61fdb2720 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c | |||
@@ -734,7 +734,7 @@ int nfs_updatepage(struct file *file, struct page *page, | |||
734 | */ | 734 | */ |
735 | if (nfs_write_pageuptodate(page, inode) && | 735 | if (nfs_write_pageuptodate(page, inode) && |
736 | inode->i_flock == NULL && | 736 | inode->i_flock == NULL && |
737 | !(file->f_mode & O_SYNC)) { | 737 | !(file->f_flags & O_SYNC)) { |
738 | count = max(count + offset, nfs_page_length(page)); | 738 | count = max(count + offset, nfs_page_length(page)); |
739 | offset = 0; | 739 | offset = 0; |
740 | } | 740 | } |