diff options
| -rw-r--r-- | fs/compat.c | 4 | ||||
| -rw-r--r-- | fs/read_write.c | 63 | ||||
| -rw-r--r-- | fs/splice.c | 8 | ||||
| -rw-r--r-- | include/linux/mm.h | 3 | ||||
| -rw-r--r-- | include/linux/security.h | 59 | ||||
| -rw-r--r-- | init/do_mounts.c | 1 | ||||
| -rw-r--r-- | mm/mmap.c | 4 | ||||
| -rw-r--r-- | security/dummy.c | 36 | ||||
| -rw-r--r-- | security/keys/proc.c | 4 | ||||
| -rw-r--r-- | security/security.c | 31 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 754 | ||||
| -rw-r--r-- | security/selinux/include/objsec.h | 1 | ||||
| -rw-r--r-- | security/selinux/selinuxfs.c | 2 | ||||
| -rw-r--r-- | security/selinux/ss/avtab.c | 2 | ||||
| -rw-r--r-- | security/selinux/ss/mls.c | 11 |
15 files changed, 642 insertions, 341 deletions
diff --git a/fs/compat.c b/fs/compat.c index 15078ce4c04a..5216c3fd7517 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
| @@ -1104,10 +1104,6 @@ static ssize_t compat_do_readv_writev(int type, struct file *file, | |||
| 1104 | if (ret < 0) | 1104 | if (ret < 0) |
| 1105 | goto out; | 1105 | goto out; |
| 1106 | 1106 | ||
| 1107 | ret = security_file_permission(file, type == READ ? MAY_READ:MAY_WRITE); | ||
| 1108 | if (ret) | ||
| 1109 | goto out; | ||
| 1110 | |||
| 1111 | fnv = NULL; | 1107 | fnv = NULL; |
| 1112 | if (type == READ) { | 1108 | if (type == READ) { |
| 1113 | fn = file->f_op->read; | 1109 | fn = file->f_op->read; |
diff --git a/fs/read_write.c b/fs/read_write.c index ea1f94cc722e..c4d3d17923f1 100644 --- a/fs/read_write.c +++ b/fs/read_write.c | |||
| @@ -197,25 +197,27 @@ int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count | |||
| 197 | { | 197 | { |
| 198 | struct inode *inode; | 198 | struct inode *inode; |
| 199 | loff_t pos; | 199 | loff_t pos; |
| 200 | int retval = -EINVAL; | ||
| 200 | 201 | ||
| 201 | inode = file->f_path.dentry->d_inode; | 202 | inode = file->f_path.dentry->d_inode; |
| 202 | if (unlikely((ssize_t) count < 0)) | 203 | if (unlikely((ssize_t) count < 0)) |
| 203 | goto Einval; | 204 | return retval; |
| 204 | pos = *ppos; | 205 | pos = *ppos; |
| 205 | if (unlikely((pos < 0) || (loff_t) (pos + count) < 0)) | 206 | if (unlikely((pos < 0) || (loff_t) (pos + count) < 0)) |
| 206 | goto Einval; | 207 | return retval; |
| 207 | 208 | ||
| 208 | if (unlikely(inode->i_flock && mandatory_lock(inode))) { | 209 | if (unlikely(inode->i_flock && mandatory_lock(inode))) { |
| 209 | int retval = locks_mandatory_area( | 210 | retval = locks_mandatory_area( |
| 210 | read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, | 211 | read_write == READ ? FLOCK_VERIFY_READ : FLOCK_VERIFY_WRITE, |
| 211 | inode, file, pos, count); | 212 | inode, file, pos, count); |
| 212 | if (retval < 0) | 213 | if (retval < 0) |
| 213 | return retval; | 214 | return retval; |
| 214 | } | 215 | } |
| 216 | retval = security_file_permission(file, | ||
| 217 | read_write == READ ? MAY_READ : MAY_WRITE); | ||
| 218 | if (retval) | ||
| 219 | return retval; | ||
| 215 | return count > MAX_RW_COUNT ? MAX_RW_COUNT : count; | 220 | return count > MAX_RW_COUNT ? MAX_RW_COUNT : count; |
| 216 | |||
| 217 | Einval: | ||
| 218 | return -EINVAL; | ||
| 219 | } | 221 | } |
| 220 | 222 | ||
| 221 | static void wait_on_retry_sync_kiocb(struct kiocb *iocb) | 223 | static void wait_on_retry_sync_kiocb(struct kiocb *iocb) |
| @@ -267,18 +269,15 @@ ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) | |||
| 267 | ret = rw_verify_area(READ, file, pos, count); | 269 | ret = rw_verify_area(READ, file, pos, count); |
| 268 | if (ret >= 0) { | 270 | if (ret >= 0) { |
| 269 | count = ret; | 271 | count = ret; |
| 270 | ret = security_file_permission (file, MAY_READ); | 272 | if (file->f_op->read) |
| 271 | if (!ret) { | 273 | ret = file->f_op->read(file, buf, count, pos); |
| 272 | if (file->f_op->read) | 274 | else |
| 273 | ret = file->f_op->read(file, buf, count, pos); | 275 | ret = do_sync_read(file, buf, count, pos); |
| 274 | else | 276 | if (ret > 0) { |
| 275 | ret = do_sync_read(file, buf, count, pos); | 277 | fsnotify_access(file->f_path.dentry); |
| 276 | if (ret > 0) { | 278 | add_rchar(current, ret); |
| 277 | fsnotify_access(file->f_path.dentry); | ||
| 278 | add_rchar(current, ret); | ||
| 279 | } | ||
| 280 | inc_syscr(current); | ||
| 281 | } | 279 | } |
| 280 | inc_syscr(current); | ||
| 282 | } | 281 | } |
| 283 | 282 | ||
| 284 | return ret; | 283 | return ret; |
| @@ -325,18 +324,15 @@ ssize_t vfs_write(struct file *file, const char __user *buf, size_t count, loff_ | |||
| 325 | ret = rw_verify_area(WRITE, file, pos, count); | 324 | ret = rw_verify_area(WRITE, file, pos, count); |
| 326 | if (ret >= 0) { | 325 | if (ret >= 0) { |
| 327 | count = ret; | 326 | count = ret; |
| 328 | ret = security_file_permission (file, MAY_WRITE); | 327 | if (file->f_op->write) |
| 329 | if (!ret) { | 328 | ret = file->f_op->write(file, buf, count, pos); |
| 330 | if (file->f_op->write) | 329 | else |
| 331 | ret = file->f_op->write(file, buf, count, pos); | 330 | ret = do_sync_write(file, buf, count, pos); |
| 332 | else | 331 | if (ret > 0) { |
| 333 | ret = do_sync_write(file, buf, count, pos); | 332 | fsnotify_modify(file->f_path.dentry); |
| 334 | if (ret > 0) { | 333 | add_wchar(current, ret); |
| 335 | fsnotify_modify(file->f_path.dentry); | ||
| 336 | add_wchar(current, ret); | ||
| 337 | } | ||
| 338 | inc_syscw(current); | ||
| 339 | } | 334 | } |
| 335 | inc_syscw(current); | ||
| 340 | } | 336 | } |
| 341 | 337 | ||
| 342 | return ret; | 338 | return ret; |
| @@ -603,9 +599,6 @@ static ssize_t do_readv_writev(int type, struct file *file, | |||
| 603 | ret = rw_verify_area(type, file, pos, tot_len); | 599 | ret = rw_verify_area(type, file, pos, tot_len); |
| 604 | if (ret < 0) | 600 | if (ret < 0) |
| 605 | goto out; | 601 | goto out; |
| 606 | ret = security_file_permission(file, type == READ ? MAY_READ : MAY_WRITE); | ||
| 607 | if (ret) | ||
| 608 | goto out; | ||
| 609 | 602 | ||
| 610 | fnv = NULL; | 603 | fnv = NULL; |
| 611 | if (type == READ) { | 604 | if (type == READ) { |
| @@ -737,10 +730,6 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
| 737 | goto fput_in; | 730 | goto fput_in; |
| 738 | count = retval; | 731 | count = retval; |
| 739 | 732 | ||
| 740 | retval = security_file_permission (in_file, MAY_READ); | ||
| 741 | if (retval) | ||
| 742 | goto fput_in; | ||
| 743 | |||
| 744 | /* | 733 | /* |
| 745 | * Get output file, and verify that it is ok.. | 734 | * Get output file, and verify that it is ok.. |
| 746 | */ | 735 | */ |
| @@ -759,10 +748,6 @@ static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos, | |||
| 759 | goto fput_out; | 748 | goto fput_out; |
| 760 | count = retval; | 749 | count = retval; |
| 761 | 750 | ||
| 762 | retval = security_file_permission (out_file, MAY_WRITE); | ||
| 763 | if (retval) | ||
| 764 | goto fput_out; | ||
| 765 | |||
| 766 | if (!max) | 751 | if (!max) |
| 767 | max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); | 752 | max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes); |
| 768 | 753 | ||
diff --git a/fs/splice.c b/fs/splice.c index 6bdcb6107bc3..56b802bfbfa4 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -908,10 +908,6 @@ static long do_splice_from(struct pipe_inode_info *pipe, struct file *out, | |||
| 908 | if (unlikely(ret < 0)) | 908 | if (unlikely(ret < 0)) |
| 909 | return ret; | 909 | return ret; |
| 910 | 910 | ||
| 911 | ret = security_file_permission(out, MAY_WRITE); | ||
| 912 | if (unlikely(ret < 0)) | ||
| 913 | return ret; | ||
| 914 | |||
| 915 | return out->f_op->splice_write(pipe, out, ppos, len, flags); | 911 | return out->f_op->splice_write(pipe, out, ppos, len, flags); |
| 916 | } | 912 | } |
| 917 | 913 | ||
| @@ -934,10 +930,6 @@ static long do_splice_to(struct file *in, loff_t *ppos, | |||
| 934 | if (unlikely(ret < 0)) | 930 | if (unlikely(ret < 0)) |
| 935 | return ret; | 931 | return ret; |
| 936 | 932 | ||
| 937 | ret = security_file_permission(in, MAY_READ); | ||
| 938 | if (unlikely(ret < 0)) | ||
| 939 | return ret; | ||
| 940 | |||
| 941 | return in->f_op->splice_read(in, ppos, pipe, len, flags); | 933 | return in->f_op->splice_read(in, ppos, pipe, len, flags); |
| 942 | } | 934 | } |
| 943 | 935 | ||
diff --git a/include/linux/mm.h b/include/linux/mm.h index 1b7b95c67aca..1897ca223eca 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | #include <linux/prio_tree.h> | 12 | #include <linux/prio_tree.h> |
| 13 | #include <linux/debug_locks.h> | 13 | #include <linux/debug_locks.h> |
| 14 | #include <linux/mm_types.h> | 14 | #include <linux/mm_types.h> |
| 15 | #include <linux/security.h> | ||
| 16 | 15 | ||
| 17 | struct mempolicy; | 16 | struct mempolicy; |
| 18 | struct anon_vma; | 17 | struct anon_vma; |
| @@ -34,6 +33,8 @@ extern int sysctl_legacy_va_layout; | |||
| 34 | #define sysctl_legacy_va_layout 0 | 33 | #define sysctl_legacy_va_layout 0 |
| 35 | #endif | 34 | #endif |
| 36 | 35 | ||
| 36 | extern unsigned long mmap_min_addr; | ||
| 37 | |||
| 37 | #include <asm/page.h> | 38 | #include <asm/page.h> |
| 38 | #include <asm/pgtable.h> | 39 | #include <asm/pgtable.h> |
| 39 | #include <asm/processor.h> | 40 | #include <asm/processor.h> |
diff --git a/include/linux/security.h b/include/linux/security.h index ac050830a873..d24974262dc6 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
| @@ -34,6 +34,12 @@ | |||
| 34 | #include <linux/xfrm.h> | 34 | #include <linux/xfrm.h> |
| 35 | #include <net/flow.h> | 35 | #include <net/flow.h> |
| 36 | 36 | ||
| 37 | /* only a char in selinux superblock security struct flags */ | ||
| 38 | #define FSCONTEXT_MNT 0x01 | ||
| 39 | #define CONTEXT_MNT 0x02 | ||
| 40 | #define ROOTCONTEXT_MNT 0x04 | ||
| 41 | #define DEFCONTEXT_MNT 0x08 | ||
| 42 | |||
| 37 | /* | 43 | /* |
| 38 | * Bounding set | 44 | * Bounding set |
| 39 | */ | 45 | */ |
| @@ -243,9 +249,6 @@ struct request_sock; | |||
| 243 | * @mnt contains the mounted file system. | 249 | * @mnt contains the mounted file system. |
| 244 | * @flags contains the new filesystem flags. | 250 | * @flags contains the new filesystem flags. |
| 245 | * @data contains the filesystem-specific data. | 251 | * @data contains the filesystem-specific data. |
| 246 | * @sb_post_mountroot: | ||
| 247 | * Update the security module's state when the root filesystem is mounted. | ||
| 248 | * This hook is only called if the mount was successful. | ||
| 249 | * @sb_post_addmount: | 252 | * @sb_post_addmount: |
| 250 | * Update the security module's state when a filesystem is mounted. | 253 | * Update the security module's state when a filesystem is mounted. |
| 251 | * This hook is called any time a mount is successfully grafetd to | 254 | * This hook is called any time a mount is successfully grafetd to |
| @@ -261,6 +264,22 @@ struct request_sock; | |||
| 261 | * Update module state after a successful pivot. | 264 | * Update module state after a successful pivot. |
| 262 | * @old_nd contains the nameidata structure for the old root. | 265 | * @old_nd contains the nameidata structure for the old root. |
| 263 | * @new_nd contains the nameidata structure for the new root. | 266 | * @new_nd contains the nameidata structure for the new root. |
| 267 | * @sb_get_mnt_opts: | ||
| 268 | * Get the security relevant mount options used for a superblock | ||
| 269 | * @sb the superblock to get security mount options from | ||
| 270 | * @mount_options array for pointers to mount options | ||
| 271 | * @mount_flags array of ints specifying what each mount options is | ||
| 272 | * @num_opts number of options in the arrays | ||
| 273 | * @sb_set_mnt_opts: | ||
| 274 | * Set the security relevant mount options used for a superblock | ||
| 275 | * @sb the superblock to set security mount options for | ||
| 276 | * @mount_options array for pointers to mount options | ||
| 277 | * @mount_flags array of ints specifying what each mount options is | ||
| 278 | * @num_opts number of options in the arrays | ||
| 279 | * @sb_clone_mnt_opts: | ||
| 280 | * Copy all security options from a given superblock to another | ||
| 281 | * @oldsb old superblock which contain information to clone | ||
| 282 | * @newsb new superblock which needs filled in | ||
| 264 | * | 283 | * |
| 265 | * Security hooks for inode operations. | 284 | * Security hooks for inode operations. |
| 266 | * | 285 | * |
| @@ -1183,6 +1202,10 @@ struct request_sock; | |||
| 1183 | * Convert secid to security context. | 1202 | * Convert secid to security context. |
| 1184 | * @secid contains the security ID. | 1203 | * @secid contains the security ID. |
| 1185 | * @secdata contains the pointer that stores the converted security context. | 1204 | * @secdata contains the pointer that stores the converted security context. |
| 1205 | * @secctx_to_secid: | ||
| 1206 | * Convert security context to secid. | ||
| 1207 | * @secid contains the pointer to the generated security ID. | ||
| 1208 | * @secdata contains the security context. | ||
| 1186 | * | 1209 | * |
| 1187 | * @release_secctx: | 1210 | * @release_secctx: |
| 1188 | * Release the security context. | 1211 | * Release the security context. |
| @@ -1235,13 +1258,19 @@ struct security_operations { | |||
| 1235 | void (*sb_umount_busy) (struct vfsmount * mnt); | 1258 | void (*sb_umount_busy) (struct vfsmount * mnt); |
| 1236 | void (*sb_post_remount) (struct vfsmount * mnt, | 1259 | void (*sb_post_remount) (struct vfsmount * mnt, |
| 1237 | unsigned long flags, void *data); | 1260 | unsigned long flags, void *data); |
| 1238 | void (*sb_post_mountroot) (void); | ||
| 1239 | void (*sb_post_addmount) (struct vfsmount * mnt, | 1261 | void (*sb_post_addmount) (struct vfsmount * mnt, |
| 1240 | struct nameidata * mountpoint_nd); | 1262 | struct nameidata * mountpoint_nd); |
| 1241 | int (*sb_pivotroot) (struct nameidata * old_nd, | 1263 | int (*sb_pivotroot) (struct nameidata * old_nd, |
| 1242 | struct nameidata * new_nd); | 1264 | struct nameidata * new_nd); |
| 1243 | void (*sb_post_pivotroot) (struct nameidata * old_nd, | 1265 | void (*sb_post_pivotroot) (struct nameidata * old_nd, |
| 1244 | struct nameidata * new_nd); | 1266 | struct nameidata * new_nd); |
| 1267 | int (*sb_get_mnt_opts) (const struct super_block *sb, | ||
| 1268 | char ***mount_options, int **flags, | ||
| 1269 | int *num_opts); | ||
| 1270 | int (*sb_set_mnt_opts) (struct super_block *sb, char **mount_options, | ||
| 1271 | int *flags, int num_opts); | ||
| 1272 | void (*sb_clone_mnt_opts) (const struct super_block *oldsb, | ||
| 1273 | struct super_block *newsb); | ||
| 1245 | 1274 | ||
| 1246 | int (*inode_alloc_security) (struct inode *inode); | 1275 | int (*inode_alloc_security) (struct inode *inode); |
| 1247 | void (*inode_free_security) (struct inode *inode); | 1276 | void (*inode_free_security) (struct inode *inode); |
| @@ -1371,6 +1400,7 @@ struct security_operations { | |||
| 1371 | int (*getprocattr)(struct task_struct *p, char *name, char **value); | 1400 | int (*getprocattr)(struct task_struct *p, char *name, char **value); |
| 1372 | int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size); | 1401 | int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size); |
| 1373 | int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen); | 1402 | int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen); |
| 1403 | int (*secctx_to_secid)(char *secdata, u32 seclen, u32 *secid); | ||
| 1374 | void (*release_secctx)(char *secdata, u32 seclen); | 1404 | void (*release_secctx)(char *secdata, u32 seclen); |
| 1375 | 1405 | ||
| 1376 | #ifdef CONFIG_SECURITY_NETWORK | 1406 | #ifdef CONFIG_SECURITY_NETWORK |
| @@ -1495,10 +1525,16 @@ int security_sb_umount(struct vfsmount *mnt, int flags); | |||
| 1495 | void security_sb_umount_close(struct vfsmount *mnt); | 1525 | void security_sb_umount_close(struct vfsmount *mnt); |
| 1496 | void security_sb_umount_busy(struct vfsmount *mnt); | 1526 | void security_sb_umount_busy(struct vfsmount *mnt); |
| 1497 | void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data); | 1527 | void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data); |
| 1498 | void security_sb_post_mountroot(void); | ||
| 1499 | void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd); | 1528 | void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd); |
| 1500 | int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd); | 1529 | int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd); |
| 1501 | void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd); | 1530 | void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd); |
| 1531 | int security_sb_get_mnt_opts(const struct super_block *sb, char ***mount_options, | ||
| 1532 | int **flags, int *num_opts); | ||
| 1533 | int security_sb_set_mnt_opts(struct super_block *sb, char **mount_options, | ||
| 1534 | int *flags, int num_opts); | ||
| 1535 | void security_sb_clone_mnt_opts(const struct super_block *oldsb, | ||
| 1536 | struct super_block *newsb); | ||
| 1537 | |||
| 1502 | int security_inode_alloc(struct inode *inode); | 1538 | int security_inode_alloc(struct inode *inode); |
| 1503 | void security_inode_free(struct inode *inode); | 1539 | void security_inode_free(struct inode *inode); |
| 1504 | int security_inode_init_security(struct inode *inode, struct inode *dir, | 1540 | int security_inode_init_security(struct inode *inode, struct inode *dir, |
| @@ -1603,6 +1639,7 @@ int security_setprocattr(struct task_struct *p, char *name, void *value, size_t | |||
| 1603 | int security_netlink_send(struct sock *sk, struct sk_buff *skb); | 1639 | int security_netlink_send(struct sock *sk, struct sk_buff *skb); |
| 1604 | int security_netlink_recv(struct sk_buff *skb, int cap); | 1640 | int security_netlink_recv(struct sk_buff *skb, int cap); |
| 1605 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); | 1641 | int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); |
| 1642 | int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid); | ||
| 1606 | void security_release_secctx(char *secdata, u32 seclen); | 1643 | void security_release_secctx(char *secdata, u32 seclen); |
| 1607 | 1644 | ||
| 1608 | #else /* CONFIG_SECURITY */ | 1645 | #else /* CONFIG_SECURITY */ |
| @@ -1777,9 +1814,6 @@ static inline void security_sb_post_remount (struct vfsmount *mnt, | |||
| 1777 | unsigned long flags, void *data) | 1814 | unsigned long flags, void *data) |
| 1778 | { } | 1815 | { } |
| 1779 | 1816 | ||
| 1780 | static inline void security_sb_post_mountroot (void) | ||
| 1781 | { } | ||
| 1782 | |||
| 1783 | static inline void security_sb_post_addmount (struct vfsmount *mnt, | 1817 | static inline void security_sb_post_addmount (struct vfsmount *mnt, |
| 1784 | struct nameidata *mountpoint_nd) | 1818 | struct nameidata *mountpoint_nd) |
| 1785 | { } | 1819 | { } |
| @@ -2266,7 +2300,7 @@ static inline struct dentry *securityfs_create_file(const char *name, | |||
| 2266 | mode_t mode, | 2300 | mode_t mode, |
| 2267 | struct dentry *parent, | 2301 | struct dentry *parent, |
| 2268 | void *data, | 2302 | void *data, |
| 2269 | struct file_operations *fops) | 2303 | const struct file_operations *fops) |
| 2270 | { | 2304 | { |
| 2271 | return ERR_PTR(-ENODEV); | 2305 | return ERR_PTR(-ENODEV); |
| 2272 | } | 2306 | } |
| @@ -2280,6 +2314,13 @@ static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *secle | |||
| 2280 | return -EOPNOTSUPP; | 2314 | return -EOPNOTSUPP; |
| 2281 | } | 2315 | } |
| 2282 | 2316 | ||
| 2317 | static inline int security_secctx_to_secid(char *secdata, | ||
| 2318 | u32 seclen, | ||
| 2319 | u32 *secid) | ||
| 2320 | { | ||
| 2321 | return -EOPNOTSUPP; | ||
| 2322 | } | ||
| 2323 | |||
| 2283 | static inline void security_release_secctx(char *secdata, u32 seclen) | 2324 | static inline void security_release_secctx(char *secdata, u32 seclen) |
| 2284 | { | 2325 | { |
| 2285 | } | 2326 | } |
diff --git a/init/do_mounts.c b/init/do_mounts.c index 2ae5b8462399..1161dfd7b0d3 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c | |||
| @@ -378,6 +378,5 @@ void __init prepare_namespace(void) | |||
| 378 | out: | 378 | out: |
| 379 | sys_mount(".", "/", NULL, MS_MOVE, NULL); | 379 | sys_mount(".", "/", NULL, MS_MOVE, NULL); |
| 380 | sys_chroot("."); | 380 | sys_chroot("."); |
| 381 | security_sb_post_mountroot(); | ||
| 382 | } | 381 | } |
| 383 | 382 | ||
| @@ -1620,7 +1620,7 @@ static inline int expand_downwards(struct vm_area_struct *vma, | |||
| 1620 | return -ENOMEM; | 1620 | return -ENOMEM; |
| 1621 | 1621 | ||
| 1622 | address &= PAGE_MASK; | 1622 | address &= PAGE_MASK; |
| 1623 | error = security_file_mmap(0, 0, 0, 0, address, 1); | 1623 | error = security_file_mmap(NULL, 0, 0, 0, address, 1); |
| 1624 | if (error) | 1624 | if (error) |
| 1625 | return error; | 1625 | return error; |
| 1626 | 1626 | ||
| @@ -1941,7 +1941,7 @@ unsigned long do_brk(unsigned long addr, unsigned long len) | |||
| 1941 | if (is_hugepage_only_range(mm, addr, len)) | 1941 | if (is_hugepage_only_range(mm, addr, len)) |
| 1942 | return -EINVAL; | 1942 | return -EINVAL; |
| 1943 | 1943 | ||
| 1944 | error = security_file_mmap(0, 0, 0, 0, addr, 1); | 1944 | error = security_file_mmap(NULL, 0, 0, 0, addr, 1); |
| 1945 | if (error) | 1945 | if (error) |
| 1946 | return error; | 1946 | return error; |
| 1947 | 1947 | ||
diff --git a/security/dummy.c b/security/dummy.c index 3ccfbbe973b6..48d4b0a52737 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
| @@ -225,22 +225,40 @@ static void dummy_sb_post_remount (struct vfsmount *mnt, unsigned long flags, | |||
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | 227 | ||
| 228 | static void dummy_sb_post_mountroot (void) | 228 | static void dummy_sb_post_addmount (struct vfsmount *mnt, struct nameidata *nd) |
| 229 | { | 229 | { |
| 230 | return; | 230 | return; |
| 231 | } | 231 | } |
| 232 | 232 | ||
| 233 | static void dummy_sb_post_addmount (struct vfsmount *mnt, struct nameidata *nd) | 233 | static int dummy_sb_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd) |
| 234 | { | ||
| 235 | return 0; | ||
| 236 | } | ||
| 237 | |||
| 238 | static void dummy_sb_post_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd) | ||
| 234 | { | 239 | { |
| 235 | return; | 240 | return; |
| 236 | } | 241 | } |
| 237 | 242 | ||
| 238 | static int dummy_sb_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd) | 243 | static int dummy_sb_get_mnt_opts(const struct super_block *sb, char ***mount_options, |
| 244 | int **flags, int *num_opts) | ||
| 239 | { | 245 | { |
| 246 | *mount_options = NULL; | ||
| 247 | *flags = NULL; | ||
| 248 | *num_opts = 0; | ||
| 240 | return 0; | 249 | return 0; |
| 241 | } | 250 | } |
| 242 | 251 | ||
| 243 | static void dummy_sb_post_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd) | 252 | static int dummy_sb_set_mnt_opts(struct super_block *sb, char **mount_options, |
| 253 | int *flags, int num_opts) | ||
| 254 | { | ||
| 255 | if (unlikely(num_opts)) | ||
| 256 | return -EOPNOTSUPP; | ||
| 257 | return 0; | ||
| 258 | } | ||
| 259 | |||
| 260 | static void dummy_sb_clone_mnt_opts(const struct super_block *oldsb, | ||
| 261 | struct super_block *newsb) | ||
| 244 | { | 262 | { |
| 245 | return; | 263 | return; |
| 246 | } | 264 | } |
| @@ -928,6 +946,11 @@ static int dummy_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | |||
| 928 | return -EOPNOTSUPP; | 946 | return -EOPNOTSUPP; |
| 929 | } | 947 | } |
| 930 | 948 | ||
| 949 | static int dummy_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) | ||
| 950 | { | ||
| 951 | return -EOPNOTSUPP; | ||
| 952 | } | ||
| 953 | |||
| 931 | static void dummy_release_secctx(char *secdata, u32 seclen) | 954 | static void dummy_release_secctx(char *secdata, u32 seclen) |
| 932 | { | 955 | { |
| 933 | } | 956 | } |
| @@ -994,10 +1017,12 @@ void security_fixup_ops (struct security_operations *ops) | |||
| 994 | set_to_dummy_if_null(ops, sb_umount_close); | 1017 | set_to_dummy_if_null(ops, sb_umount_close); |
| 995 | set_to_dummy_if_null(ops, sb_umount_busy); | 1018 | set_to_dummy_if_null(ops, sb_umount_busy); |
| 996 | set_to_dummy_if_null(ops, sb_post_remount); | 1019 | set_to_dummy_if_null(ops, sb_post_remount); |
| 997 | set_to_dummy_if_null(ops, sb_post_mountroot); | ||
| 998 | set_to_dummy_if_null(ops, sb_post_addmount); | 1020 | set_to_dummy_if_null(ops, sb_post_addmount); |
| 999 | set_to_dummy_if_null(ops, sb_pivotroot); | 1021 | set_to_dummy_if_null(ops, sb_pivotroot); |
| 1000 | set_to_dummy_if_null(ops, sb_post_pivotroot); | 1022 | set_to_dummy_if_null(ops, sb_post_pivotroot); |
| 1023 | set_to_dummy_if_null(ops, sb_get_mnt_opts); | ||
| 1024 | set_to_dummy_if_null(ops, sb_set_mnt_opts); | ||
| 1025 | set_to_dummy_if_null(ops, sb_clone_mnt_opts); | ||
| 1001 | set_to_dummy_if_null(ops, inode_alloc_security); | 1026 | set_to_dummy_if_null(ops, inode_alloc_security); |
| 1002 | set_to_dummy_if_null(ops, inode_free_security); | 1027 | set_to_dummy_if_null(ops, inode_free_security); |
| 1003 | set_to_dummy_if_null(ops, inode_init_security); | 1028 | set_to_dummy_if_null(ops, inode_init_security); |
| @@ -1086,6 +1111,7 @@ void security_fixup_ops (struct security_operations *ops) | |||
| 1086 | set_to_dummy_if_null(ops, getprocattr); | 1111 | set_to_dummy_if_null(ops, getprocattr); |
| 1087 | set_to_dummy_if_null(ops, setprocattr); | 1112 | set_to_dummy_if_null(ops, setprocattr); |
| 1088 | set_to_dummy_if_null(ops, secid_to_secctx); | 1113 | set_to_dummy_if_null(ops, secid_to_secctx); |
| 1114 | set_to_dummy_if_null(ops, secctx_to_secid); | ||
| 1089 | set_to_dummy_if_null(ops, release_secctx); | 1115 | set_to_dummy_if_null(ops, release_secctx); |
| 1090 | #ifdef CONFIG_SECURITY_NETWORK | 1116 | #ifdef CONFIG_SECURITY_NETWORK |
| 1091 | set_to_dummy_if_null(ops, unix_stream_connect); | 1117 | set_to_dummy_if_null(ops, unix_stream_connect); |
diff --git a/security/keys/proc.c b/security/keys/proc.c index 3e0d0a6e224f..694126003ed3 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
| @@ -26,7 +26,7 @@ static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos); | |||
| 26 | static void proc_keys_stop(struct seq_file *p, void *v); | 26 | static void proc_keys_stop(struct seq_file *p, void *v); |
| 27 | static int proc_keys_show(struct seq_file *m, void *v); | 27 | static int proc_keys_show(struct seq_file *m, void *v); |
| 28 | 28 | ||
| 29 | static struct seq_operations proc_keys_ops = { | 29 | static const struct seq_operations proc_keys_ops = { |
| 30 | .start = proc_keys_start, | 30 | .start = proc_keys_start, |
| 31 | .next = proc_keys_next, | 31 | .next = proc_keys_next, |
| 32 | .stop = proc_keys_stop, | 32 | .stop = proc_keys_stop, |
| @@ -47,7 +47,7 @@ static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos); | |||
| 47 | static void proc_key_users_stop(struct seq_file *p, void *v); | 47 | static void proc_key_users_stop(struct seq_file *p, void *v); |
| 48 | static int proc_key_users_show(struct seq_file *m, void *v); | 48 | static int proc_key_users_show(struct seq_file *m, void *v); |
| 49 | 49 | ||
| 50 | static struct seq_operations proc_key_users_ops = { | 50 | static const struct seq_operations proc_key_users_ops = { |
| 51 | .start = proc_key_users_start, | 51 | .start = proc_key_users_start, |
| 52 | .next = proc_key_users_next, | 52 | .next = proc_key_users_next, |
| 53 | .stop = proc_key_users_stop, | 53 | .stop = proc_key_users_stop, |
diff --git a/security/security.c b/security/security.c index 0e1f1f124368..ca475ca206e4 100644 --- a/security/security.c +++ b/security/security.c | |||
| @@ -288,11 +288,6 @@ void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *d | |||
| 288 | security_ops->sb_post_remount(mnt, flags, data); | 288 | security_ops->sb_post_remount(mnt, flags, data); |
| 289 | } | 289 | } |
| 290 | 290 | ||
| 291 | void security_sb_post_mountroot(void) | ||
| 292 | { | ||
| 293 | security_ops->sb_post_mountroot(); | ||
| 294 | } | ||
| 295 | |||
| 296 | void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd) | 291 | void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd) |
| 297 | { | 292 | { |
| 298 | security_ops->sb_post_addmount(mnt, mountpoint_nd); | 293 | security_ops->sb_post_addmount(mnt, mountpoint_nd); |
| @@ -308,6 +303,26 @@ void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_ | |||
| 308 | security_ops->sb_post_pivotroot(old_nd, new_nd); | 303 | security_ops->sb_post_pivotroot(old_nd, new_nd); |
| 309 | } | 304 | } |
| 310 | 305 | ||
| 306 | int security_sb_get_mnt_opts(const struct super_block *sb, | ||
| 307 | char ***mount_options, | ||
| 308 | int **flags, int *num_opts) | ||
| 309 | { | ||
| 310 | return security_ops->sb_get_mnt_opts(sb, mount_options, flags, num_opts); | ||
| 311 | } | ||
| 312 | |||
| 313 | int security_sb_set_mnt_opts(struct super_block *sb, | ||
| 314 | char **mount_options, | ||
| 315 | int *flags, int num_opts) | ||
| 316 | { | ||
| 317 | return security_ops->sb_set_mnt_opts(sb, mount_options, flags, num_opts); | ||
| 318 | } | ||
| 319 | |||
| 320 | void security_sb_clone_mnt_opts(const struct super_block *oldsb, | ||
| 321 | struct super_block *newsb) | ||
| 322 | { | ||
| 323 | security_ops->sb_clone_mnt_opts(oldsb, newsb); | ||
| 324 | } | ||
| 325 | |||
| 311 | int security_inode_alloc(struct inode *inode) | 326 | int security_inode_alloc(struct inode *inode) |
| 312 | { | 327 | { |
| 313 | inode->i_security = NULL; | 328 | inode->i_security = NULL; |
| @@ -816,6 +831,12 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | |||
| 816 | } | 831 | } |
| 817 | EXPORT_SYMBOL(security_secid_to_secctx); | 832 | EXPORT_SYMBOL(security_secid_to_secctx); |
| 818 | 833 | ||
| 834 | int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) | ||
| 835 | { | ||
| 836 | return security_ops->secctx_to_secid(secdata, seclen, secid); | ||
| 837 | } | ||
| 838 | EXPORT_SYMBOL(security_secctx_to_secid); | ||
| 839 | |||
| 819 | void security_release_secctx(char *secdata, u32 seclen) | 840 | void security_release_secctx(char *secdata, u32 seclen) |
| 820 | { | 841 | { |
| 821 | return security_ops->release_secctx(secdata, seclen); | 842 | return security_ops->release_secctx(secdata, seclen); |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 9f3124b08867..0396354fff95 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -82,6 +82,8 @@ | |||
| 82 | #define XATTR_SELINUX_SUFFIX "selinux" | 82 | #define XATTR_SELINUX_SUFFIX "selinux" |
| 83 | #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX | 83 | #define XATTR_NAME_SELINUX XATTR_SECURITY_PREFIX XATTR_SELINUX_SUFFIX |
| 84 | 84 | ||
| 85 | #define NUM_SEL_MNT_OPTS 4 | ||
| 86 | |||
| 85 | extern unsigned int policydb_loaded_version; | 87 | extern unsigned int policydb_loaded_version; |
| 86 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); | 88 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); |
| 87 | extern int selinux_compat_net; | 89 | extern int selinux_compat_net; |
| @@ -321,8 +323,8 @@ enum { | |||
| 321 | Opt_error = -1, | 323 | Opt_error = -1, |
| 322 | Opt_context = 1, | 324 | Opt_context = 1, |
| 323 | Opt_fscontext = 2, | 325 | Opt_fscontext = 2, |
| 324 | Opt_defcontext = 4, | 326 | Opt_defcontext = 3, |
| 325 | Opt_rootcontext = 8, | 327 | Opt_rootcontext = 4, |
| 326 | }; | 328 | }; |
| 327 | 329 | ||
| 328 | static match_table_t tokens = { | 330 | static match_table_t tokens = { |
| @@ -366,150 +368,317 @@ static int may_context_mount_inode_relabel(u32 sid, | |||
| 366 | return rc; | 368 | return rc; |
| 367 | } | 369 | } |
| 368 | 370 | ||
| 369 | static int try_context_mount(struct super_block *sb, void *data) | 371 | static int sb_finish_set_opts(struct super_block *sb) |
| 370 | { | 372 | { |
| 371 | char *context = NULL, *defcontext = NULL; | ||
| 372 | char *fscontext = NULL, *rootcontext = NULL; | ||
| 373 | const char *name; | ||
| 374 | u32 sid; | ||
| 375 | int alloc = 0, rc = 0, seen = 0; | ||
| 376 | struct task_security_struct *tsec = current->security; | ||
| 377 | struct superblock_security_struct *sbsec = sb->s_security; | 373 | struct superblock_security_struct *sbsec = sb->s_security; |
| 374 | struct dentry *root = sb->s_root; | ||
| 375 | struct inode *root_inode = root->d_inode; | ||
| 376 | int rc = 0; | ||
| 378 | 377 | ||
| 379 | if (!data) | 378 | if (sbsec->behavior == SECURITY_FS_USE_XATTR) { |
| 380 | goto out; | 379 | /* Make sure that the xattr handler exists and that no |
| 380 | error other than -ENODATA is returned by getxattr on | ||
| 381 | the root directory. -ENODATA is ok, as this may be | ||
| 382 | the first boot of the SELinux kernel before we have | ||
| 383 | assigned xattr values to the filesystem. */ | ||
| 384 | if (!root_inode->i_op->getxattr) { | ||
| 385 | printk(KERN_WARNING "SELinux: (dev %s, type %s) has no " | ||
| 386 | "xattr support\n", sb->s_id, sb->s_type->name); | ||
| 387 | rc = -EOPNOTSUPP; | ||
| 388 | goto out; | ||
| 389 | } | ||
| 390 | rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0); | ||
| 391 | if (rc < 0 && rc != -ENODATA) { | ||
| 392 | if (rc == -EOPNOTSUPP) | ||
| 393 | printk(KERN_WARNING "SELinux: (dev %s, type " | ||
| 394 | "%s) has no security xattr handler\n", | ||
| 395 | sb->s_id, sb->s_type->name); | ||
| 396 | else | ||
| 397 | printk(KERN_WARNING "SELinux: (dev %s, type " | ||
| 398 | "%s) getxattr errno %d\n", sb->s_id, | ||
| 399 | sb->s_type->name, -rc); | ||
| 400 | goto out; | ||
| 401 | } | ||
| 402 | } | ||
| 381 | 403 | ||
| 382 | name = sb->s_type->name; | 404 | sbsec->initialized = 1; |
| 383 | 405 | ||
| 384 | if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) { | 406 | if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) |
| 407 | printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", | ||
| 408 | sb->s_id, sb->s_type->name); | ||
| 409 | else | ||
| 410 | printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n", | ||
| 411 | sb->s_id, sb->s_type->name, | ||
| 412 | labeling_behaviors[sbsec->behavior-1]); | ||
| 385 | 413 | ||
| 386 | /* NFS we understand. */ | 414 | /* Initialize the root inode. */ |
| 387 | if (!strcmp(name, "nfs")) { | 415 | rc = inode_doinit_with_dentry(root_inode, root); |
| 388 | struct nfs_mount_data *d = data; | ||
| 389 | 416 | ||
| 390 | if (d->version < NFS_MOUNT_VERSION) | 417 | /* Initialize any other inodes associated with the superblock, e.g. |
| 391 | goto out; | 418 | inodes created prior to initial policy load or inodes created |
| 419 | during get_sb by a pseudo filesystem that directly | ||
| 420 | populates itself. */ | ||
| 421 | spin_lock(&sbsec->isec_lock); | ||
| 422 | next_inode: | ||
| 423 | if (!list_empty(&sbsec->isec_head)) { | ||
| 424 | struct inode_security_struct *isec = | ||
| 425 | list_entry(sbsec->isec_head.next, | ||
| 426 | struct inode_security_struct, list); | ||
| 427 | struct inode *inode = isec->inode; | ||
| 428 | spin_unlock(&sbsec->isec_lock); | ||
| 429 | inode = igrab(inode); | ||
| 430 | if (inode) { | ||
| 431 | if (!IS_PRIVATE(inode)) | ||
| 432 | inode_doinit(inode); | ||
| 433 | iput(inode); | ||
| 434 | } | ||
| 435 | spin_lock(&sbsec->isec_lock); | ||
| 436 | list_del_init(&isec->list); | ||
| 437 | goto next_inode; | ||
| 438 | } | ||
| 439 | spin_unlock(&sbsec->isec_lock); | ||
| 440 | out: | ||
| 441 | return rc; | ||
| 442 | } | ||
| 392 | 443 | ||
| 393 | if (d->context[0]) { | 444 | /* |
| 394 | context = d->context; | 445 | * This function should allow an FS to ask what it's mount security |
| 395 | seen |= Opt_context; | 446 | * options were so it can use those later for submounts, displaying |
| 396 | } | 447 | * mount options, or whatever. |
| 397 | } else | 448 | */ |
| 398 | goto out; | 449 | static int selinux_get_mnt_opts(const struct super_block *sb, |
| 450 | char ***mount_options, int **mnt_opts_flags, | ||
| 451 | int *num_opts) | ||
| 452 | { | ||
| 453 | int rc = 0, i; | ||
| 454 | struct superblock_security_struct *sbsec = sb->s_security; | ||
| 455 | char *context = NULL; | ||
| 456 | u32 len; | ||
| 457 | char tmp; | ||
| 399 | 458 | ||
| 400 | } else { | 459 | *num_opts = 0; |
| 401 | /* Standard string-based options. */ | 460 | *mount_options = NULL; |
| 402 | char *p, *options = data; | 461 | *mnt_opts_flags = NULL; |
| 403 | 462 | ||
| 404 | while ((p = strsep(&options, "|")) != NULL) { | 463 | if (!sbsec->initialized) |
| 405 | int token; | 464 | return -EINVAL; |
| 406 | substring_t args[MAX_OPT_ARGS]; | ||
| 407 | 465 | ||
| 408 | if (!*p) | 466 | if (!ss_initialized) |
| 409 | continue; | 467 | return -EINVAL; |
| 410 | 468 | ||
| 411 | token = match_token(p, tokens, args); | 469 | /* |
| 470 | * if we ever use sbsec flags for anything other than tracking mount | ||
| 471 | * settings this is going to need a mask | ||
| 472 | */ | ||
| 473 | tmp = sbsec->flags; | ||
| 474 | /* count the number of mount options for this sb */ | ||
| 475 | for (i = 0; i < 8; i++) { | ||
| 476 | if (tmp & 0x01) | ||
| 477 | (*num_opts)++; | ||
| 478 | tmp >>= 1; | ||
| 479 | } | ||
| 412 | 480 | ||
| 413 | switch (token) { | 481 | *mount_options = kcalloc(*num_opts, sizeof(char *), GFP_ATOMIC); |
| 414 | case Opt_context: | 482 | if (!*mount_options) { |
| 415 | if (seen & (Opt_context|Opt_defcontext)) { | 483 | rc = -ENOMEM; |
| 416 | rc = -EINVAL; | 484 | goto out_free; |
| 417 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | 485 | } |
| 418 | goto out_free; | ||
| 419 | } | ||
| 420 | context = match_strdup(&args[0]); | ||
| 421 | if (!context) { | ||
| 422 | rc = -ENOMEM; | ||
| 423 | goto out_free; | ||
| 424 | } | ||
| 425 | if (!alloc) | ||
| 426 | alloc = 1; | ||
| 427 | seen |= Opt_context; | ||
| 428 | break; | ||
| 429 | 486 | ||
| 430 | case Opt_fscontext: | 487 | *mnt_opts_flags = kcalloc(*num_opts, sizeof(int), GFP_ATOMIC); |
| 431 | if (seen & Opt_fscontext) { | 488 | if (!*mnt_opts_flags) { |
| 432 | rc = -EINVAL; | 489 | rc = -ENOMEM; |
| 433 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | 490 | goto out_free; |
| 434 | goto out_free; | 491 | } |
| 435 | } | ||
| 436 | fscontext = match_strdup(&args[0]); | ||
| 437 | if (!fscontext) { | ||
| 438 | rc = -ENOMEM; | ||
| 439 | goto out_free; | ||
| 440 | } | ||
| 441 | if (!alloc) | ||
| 442 | alloc = 1; | ||
| 443 | seen |= Opt_fscontext; | ||
| 444 | break; | ||
| 445 | 492 | ||
| 446 | case Opt_rootcontext: | 493 | i = 0; |
| 447 | if (seen & Opt_rootcontext) { | 494 | if (sbsec->flags & FSCONTEXT_MNT) { |
| 448 | rc = -EINVAL; | 495 | rc = security_sid_to_context(sbsec->sid, &context, &len); |
| 449 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | 496 | if (rc) |
| 450 | goto out_free; | 497 | goto out_free; |
| 451 | } | 498 | (*mount_options)[i] = context; |
| 452 | rootcontext = match_strdup(&args[0]); | 499 | (*mnt_opts_flags)[i++] = FSCONTEXT_MNT; |
| 453 | if (!rootcontext) { | 500 | } |
| 454 | rc = -ENOMEM; | 501 | if (sbsec->flags & CONTEXT_MNT) { |
| 455 | goto out_free; | 502 | rc = security_sid_to_context(sbsec->mntpoint_sid, &context, &len); |
| 456 | } | 503 | if (rc) |
| 457 | if (!alloc) | 504 | goto out_free; |
| 458 | alloc = 1; | 505 | (*mount_options)[i] = context; |
| 459 | seen |= Opt_rootcontext; | 506 | (*mnt_opts_flags)[i++] = CONTEXT_MNT; |
| 460 | break; | 507 | } |
| 508 | if (sbsec->flags & DEFCONTEXT_MNT) { | ||
| 509 | rc = security_sid_to_context(sbsec->def_sid, &context, &len); | ||
| 510 | if (rc) | ||
| 511 | goto out_free; | ||
| 512 | (*mount_options)[i] = context; | ||
| 513 | (*mnt_opts_flags)[i++] = DEFCONTEXT_MNT; | ||
| 514 | } | ||
| 515 | if (sbsec->flags & ROOTCONTEXT_MNT) { | ||
| 516 | struct inode *root = sbsec->sb->s_root->d_inode; | ||
| 517 | struct inode_security_struct *isec = root->i_security; | ||
| 461 | 518 | ||
| 462 | case Opt_defcontext: | 519 | rc = security_sid_to_context(isec->sid, &context, &len); |
| 463 | if (sbsec->behavior != SECURITY_FS_USE_XATTR) { | 520 | if (rc) |
| 464 | rc = -EINVAL; | 521 | goto out_free; |
| 465 | printk(KERN_WARNING "SELinux: " | 522 | (*mount_options)[i] = context; |
| 466 | "defcontext option is invalid " | 523 | (*mnt_opts_flags)[i++] = ROOTCONTEXT_MNT; |
| 467 | "for this filesystem type\n"); | 524 | } |
| 468 | goto out_free; | ||
| 469 | } | ||
| 470 | if (seen & (Opt_context|Opt_defcontext)) { | ||
| 471 | rc = -EINVAL; | ||
| 472 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | ||
| 473 | goto out_free; | ||
| 474 | } | ||
| 475 | defcontext = match_strdup(&args[0]); | ||
| 476 | if (!defcontext) { | ||
| 477 | rc = -ENOMEM; | ||
| 478 | goto out_free; | ||
| 479 | } | ||
| 480 | if (!alloc) | ||
| 481 | alloc = 1; | ||
| 482 | seen |= Opt_defcontext; | ||
| 483 | break; | ||
| 484 | 525 | ||
| 485 | default: | 526 | BUG_ON(i != *num_opts); |
| 486 | rc = -EINVAL; | ||
| 487 | printk(KERN_WARNING "SELinux: unknown mount " | ||
| 488 | "option\n"); | ||
| 489 | goto out_free; | ||
| 490 | 527 | ||
| 491 | } | 528 | return 0; |
| 492 | } | 529 | |
| 493 | } | 530 | out_free: |
| 531 | /* don't leak context string if security_sid_to_context had an error */ | ||
| 532 | if (*mount_options && i) | ||
| 533 | for (; i > 0; i--) | ||
| 534 | kfree((*mount_options)[i-1]); | ||
| 535 | kfree(*mount_options); | ||
| 536 | *mount_options = NULL; | ||
| 537 | kfree(*mnt_opts_flags); | ||
| 538 | *mnt_opts_flags = NULL; | ||
| 539 | *num_opts = 0; | ||
| 540 | return rc; | ||
| 541 | } | ||
| 542 | |||
| 543 | static int bad_option(struct superblock_security_struct *sbsec, char flag, | ||
| 544 | u32 old_sid, u32 new_sid) | ||
| 545 | { | ||
| 546 | /* check if the old mount command had the same options */ | ||
| 547 | if (sbsec->initialized) | ||
| 548 | if (!(sbsec->flags & flag) || | ||
| 549 | (old_sid != new_sid)) | ||
| 550 | return 1; | ||
| 551 | |||
| 552 | /* check if we were passed the same options twice, | ||
| 553 | * aka someone passed context=a,context=b | ||
| 554 | */ | ||
| 555 | if (!sbsec->initialized) | ||
| 556 | if (sbsec->flags & flag) | ||
| 557 | return 1; | ||
| 558 | return 0; | ||
| 559 | } | ||
| 560 | /* | ||
| 561 | * Allow filesystems with binary mount data to explicitly set mount point | ||
| 562 | * labeling information. | ||
| 563 | */ | ||
| 564 | int selinux_set_mnt_opts(struct super_block *sb, char **mount_options, | ||
| 565 | int *flags, int num_opts) | ||
| 566 | { | ||
| 567 | int rc = 0, i; | ||
| 568 | struct task_security_struct *tsec = current->security; | ||
| 569 | struct superblock_security_struct *sbsec = sb->s_security; | ||
| 570 | const char *name = sb->s_type->name; | ||
| 571 | struct inode *inode = sbsec->sb->s_root->d_inode; | ||
| 572 | struct inode_security_struct *root_isec = inode->i_security; | ||
| 573 | u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; | ||
| 574 | u32 defcontext_sid = 0; | ||
| 494 | 575 | ||
| 495 | if (!seen) | 576 | mutex_lock(&sbsec->lock); |
| 577 | |||
| 578 | if (!ss_initialized) { | ||
| 579 | if (!num_opts) { | ||
| 580 | /* Defer initialization until selinux_complete_init, | ||
| 581 | after the initial policy is loaded and the security | ||
| 582 | server is ready to handle calls. */ | ||
| 583 | spin_lock(&sb_security_lock); | ||
| 584 | if (list_empty(&sbsec->list)) | ||
| 585 | list_add(&sbsec->list, &superblock_security_head); | ||
| 586 | spin_unlock(&sb_security_lock); | ||
| 587 | goto out; | ||
| 588 | } | ||
| 589 | rc = -EINVAL; | ||
| 590 | printk(KERN_WARNING "Unable to set superblock options before " | ||
| 591 | "the security server is initialized\n"); | ||
| 496 | goto out; | 592 | goto out; |
| 593 | } | ||
| 497 | 594 | ||
| 498 | /* sets the context of the superblock for the fs being mounted. */ | 595 | /* |
| 499 | if (fscontext) { | 596 | * parse the mount options, check if they are valid sids. |
| 500 | rc = security_context_to_sid(fscontext, strlen(fscontext), &sid); | 597 | * also check if someone is trying to mount the same sb more |
| 598 | * than once with different security options. | ||
| 599 | */ | ||
| 600 | for (i = 0; i < num_opts; i++) { | ||
| 601 | u32 sid; | ||
| 602 | rc = security_context_to_sid(mount_options[i], | ||
| 603 | strlen(mount_options[i]), &sid); | ||
| 501 | if (rc) { | 604 | if (rc) { |
| 502 | printk(KERN_WARNING "SELinux: security_context_to_sid" | 605 | printk(KERN_WARNING "SELinux: security_context_to_sid" |
| 503 | "(%s) failed for (dev %s, type %s) errno=%d\n", | 606 | "(%s) failed for (dev %s, type %s) errno=%d\n", |
| 504 | fscontext, sb->s_id, name, rc); | 607 | mount_options[i], sb->s_id, name, rc); |
| 505 | goto out_free; | 608 | goto out; |
| 506 | } | 609 | } |
| 610 | switch (flags[i]) { | ||
| 611 | case FSCONTEXT_MNT: | ||
| 612 | fscontext_sid = sid; | ||
| 613 | |||
| 614 | if (bad_option(sbsec, FSCONTEXT_MNT, sbsec->sid, | ||
| 615 | fscontext_sid)) | ||
| 616 | goto out_double_mount; | ||
| 617 | |||
| 618 | sbsec->flags |= FSCONTEXT_MNT; | ||
| 619 | break; | ||
| 620 | case CONTEXT_MNT: | ||
| 621 | context_sid = sid; | ||
| 622 | |||
| 623 | if (bad_option(sbsec, CONTEXT_MNT, sbsec->mntpoint_sid, | ||
| 624 | context_sid)) | ||
| 625 | goto out_double_mount; | ||
| 626 | |||
| 627 | sbsec->flags |= CONTEXT_MNT; | ||
| 628 | break; | ||
| 629 | case ROOTCONTEXT_MNT: | ||
| 630 | rootcontext_sid = sid; | ||
| 631 | |||
| 632 | if (bad_option(sbsec, ROOTCONTEXT_MNT, root_isec->sid, | ||
| 633 | rootcontext_sid)) | ||
| 634 | goto out_double_mount; | ||
| 635 | |||
| 636 | sbsec->flags |= ROOTCONTEXT_MNT; | ||
| 637 | |||
| 638 | break; | ||
| 639 | case DEFCONTEXT_MNT: | ||
| 640 | defcontext_sid = sid; | ||
| 641 | |||
| 642 | if (bad_option(sbsec, DEFCONTEXT_MNT, sbsec->def_sid, | ||
| 643 | defcontext_sid)) | ||
| 644 | goto out_double_mount; | ||
| 645 | |||
| 646 | sbsec->flags |= DEFCONTEXT_MNT; | ||
| 647 | |||
| 648 | break; | ||
| 649 | default: | ||
| 650 | rc = -EINVAL; | ||
| 651 | goto out; | ||
| 652 | } | ||
| 653 | } | ||
| 654 | |||
| 655 | if (sbsec->initialized) { | ||
| 656 | /* previously mounted with options, but not on this attempt? */ | ||
| 657 | if (sbsec->flags && !num_opts) | ||
| 658 | goto out_double_mount; | ||
| 659 | rc = 0; | ||
| 660 | goto out; | ||
| 661 | } | ||
| 662 | |||
| 663 | if (strcmp(sb->s_type->name, "proc") == 0) | ||
| 664 | sbsec->proc = 1; | ||
| 665 | |||
| 666 | /* Determine the labeling behavior to use for this filesystem type. */ | ||
| 667 | rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid); | ||
| 668 | if (rc) { | ||
| 669 | printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", | ||
| 670 | __FUNCTION__, sb->s_type->name, rc); | ||
| 671 | goto out; | ||
| 672 | } | ||
| 673 | |||
| 674 | /* sets the context of the superblock for the fs being mounted. */ | ||
| 675 | if (fscontext_sid) { | ||
| 507 | 676 | ||
| 508 | rc = may_context_mount_sb_relabel(sid, sbsec, tsec); | 677 | rc = may_context_mount_sb_relabel(fscontext_sid, sbsec, tsec); |
| 509 | if (rc) | 678 | if (rc) |
| 510 | goto out_free; | 679 | goto out; |
| 511 | 680 | ||
| 512 | sbsec->sid = sid; | 681 | sbsec->sid = fscontext_sid; |
| 513 | } | 682 | } |
| 514 | 683 | ||
| 515 | /* | 684 | /* |
| @@ -517,182 +686,250 @@ static int try_context_mount(struct super_block *sb, void *data) | |||
| 517 | * sets the label used on all file below the mountpoint, and will set | 686 | * sets the label used on all file below the mountpoint, and will set |
| 518 | * the superblock context if not already set. | 687 | * the superblock context if not already set. |
| 519 | */ | 688 | */ |
| 520 | if (context) { | 689 | if (context_sid) { |
| 521 | rc = security_context_to_sid(context, strlen(context), &sid); | 690 | if (!fscontext_sid) { |
| 522 | if (rc) { | 691 | rc = may_context_mount_sb_relabel(context_sid, sbsec, tsec); |
| 523 | printk(KERN_WARNING "SELinux: security_context_to_sid" | ||
| 524 | "(%s) failed for (dev %s, type %s) errno=%d\n", | ||
| 525 | context, sb->s_id, name, rc); | ||
| 526 | goto out_free; | ||
| 527 | } | ||
| 528 | |||
| 529 | if (!fscontext) { | ||
| 530 | rc = may_context_mount_sb_relabel(sid, sbsec, tsec); | ||
| 531 | if (rc) | 692 | if (rc) |
| 532 | goto out_free; | 693 | goto out; |
| 533 | sbsec->sid = sid; | 694 | sbsec->sid = context_sid; |
| 534 | } else { | 695 | } else { |
| 535 | rc = may_context_mount_inode_relabel(sid, sbsec, tsec); | 696 | rc = may_context_mount_inode_relabel(context_sid, sbsec, tsec); |
| 536 | if (rc) | 697 | if (rc) |
| 537 | goto out_free; | 698 | goto out; |
| 538 | } | 699 | } |
| 539 | sbsec->mntpoint_sid = sid; | 700 | if (!rootcontext_sid) |
| 701 | rootcontext_sid = context_sid; | ||
| 540 | 702 | ||
| 703 | sbsec->mntpoint_sid = context_sid; | ||
| 541 | sbsec->behavior = SECURITY_FS_USE_MNTPOINT; | 704 | sbsec->behavior = SECURITY_FS_USE_MNTPOINT; |
| 542 | } | 705 | } |
| 543 | 706 | ||
| 544 | if (rootcontext) { | 707 | if (rootcontext_sid) { |
| 545 | struct inode *inode = sb->s_root->d_inode; | 708 | rc = may_context_mount_inode_relabel(rootcontext_sid, sbsec, tsec); |
| 546 | struct inode_security_struct *isec = inode->i_security; | ||
| 547 | rc = security_context_to_sid(rootcontext, strlen(rootcontext), &sid); | ||
| 548 | if (rc) { | ||
| 549 | printk(KERN_WARNING "SELinux: security_context_to_sid" | ||
| 550 | "(%s) failed for (dev %s, type %s) errno=%d\n", | ||
| 551 | rootcontext, sb->s_id, name, rc); | ||
| 552 | goto out_free; | ||
| 553 | } | ||
| 554 | |||
| 555 | rc = may_context_mount_inode_relabel(sid, sbsec, tsec); | ||
| 556 | if (rc) | 709 | if (rc) |
| 557 | goto out_free; | 710 | goto out; |
| 558 | 711 | ||
| 559 | isec->sid = sid; | 712 | root_isec->sid = rootcontext_sid; |
| 560 | isec->initialized = 1; | 713 | root_isec->initialized = 1; |
| 561 | } | 714 | } |
| 562 | 715 | ||
| 563 | if (defcontext) { | 716 | if (defcontext_sid) { |
| 564 | rc = security_context_to_sid(defcontext, strlen(defcontext), &sid); | 717 | if (sbsec->behavior != SECURITY_FS_USE_XATTR) { |
| 565 | if (rc) { | 718 | rc = -EINVAL; |
| 566 | printk(KERN_WARNING "SELinux: security_context_to_sid" | 719 | printk(KERN_WARNING "SELinux: defcontext option is " |
| 567 | "(%s) failed for (dev %s, type %s) errno=%d\n", | 720 | "invalid for this filesystem type\n"); |
| 568 | defcontext, sb->s_id, name, rc); | 721 | goto out; |
| 569 | goto out_free; | ||
| 570 | } | 722 | } |
| 571 | 723 | ||
| 572 | if (sid == sbsec->def_sid) | 724 | if (defcontext_sid != sbsec->def_sid) { |
| 573 | goto out_free; | 725 | rc = may_context_mount_inode_relabel(defcontext_sid, |
| 574 | 726 | sbsec, tsec); | |
| 575 | rc = may_context_mount_inode_relabel(sid, sbsec, tsec); | 727 | if (rc) |
| 576 | if (rc) | 728 | goto out; |
| 577 | goto out_free; | 729 | } |
| 578 | 730 | ||
| 579 | sbsec->def_sid = sid; | 731 | sbsec->def_sid = defcontext_sid; |
| 580 | } | 732 | } |
| 581 | 733 | ||
| 582 | out_free: | 734 | rc = sb_finish_set_opts(sb); |
| 583 | if (alloc) { | ||
| 584 | kfree(context); | ||
| 585 | kfree(defcontext); | ||
| 586 | kfree(fscontext); | ||
| 587 | kfree(rootcontext); | ||
| 588 | } | ||
| 589 | out: | 735 | out: |
| 736 | mutex_unlock(&sbsec->lock); | ||
| 590 | return rc; | 737 | return rc; |
| 738 | out_double_mount: | ||
| 739 | rc = -EINVAL; | ||
| 740 | printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different " | ||
| 741 | "security settings for (dev %s, type %s)\n", sb->s_id, name); | ||
| 742 | goto out; | ||
| 591 | } | 743 | } |
| 592 | 744 | ||
| 593 | static int superblock_doinit(struct super_block *sb, void *data) | 745 | static void selinux_sb_clone_mnt_opts(const struct super_block *oldsb, |
| 746 | struct super_block *newsb) | ||
| 594 | { | 747 | { |
| 595 | struct superblock_security_struct *sbsec = sb->s_security; | 748 | const struct superblock_security_struct *oldsbsec = oldsb->s_security; |
| 596 | struct dentry *root = sb->s_root; | 749 | struct superblock_security_struct *newsbsec = newsb->s_security; |
| 597 | struct inode *inode = root->d_inode; | ||
| 598 | int rc = 0; | ||
| 599 | 750 | ||
| 600 | mutex_lock(&sbsec->lock); | 751 | int set_fscontext = (oldsbsec->flags & FSCONTEXT_MNT); |
| 601 | if (sbsec->initialized) | 752 | int set_context = (oldsbsec->flags & CONTEXT_MNT); |
| 602 | goto out; | 753 | int set_rootcontext = (oldsbsec->flags & ROOTCONTEXT_MNT); |
| 603 | 754 | ||
| 604 | if (!ss_initialized) { | 755 | /* we can't error, we can't save the info, this shouldn't get called |
| 605 | /* Defer initialization until selinux_complete_init, | 756 | * this early in the boot process. */ |
| 606 | after the initial policy is loaded and the security | 757 | BUG_ON(!ss_initialized); |
| 607 | server is ready to handle calls. */ | 758 | |
| 608 | spin_lock(&sb_security_lock); | 759 | /* this might go away sometime down the line if there is a new user |
| 609 | if (list_empty(&sbsec->list)) | 760 | * of clone, but for now, nfs better not get here... */ |
| 610 | list_add(&sbsec->list, &superblock_security_head); | 761 | BUG_ON(newsbsec->initialized); |
| 611 | spin_unlock(&sb_security_lock); | 762 | |
| 612 | goto out; | 763 | /* how can we clone if the old one wasn't set up?? */ |
| 764 | BUG_ON(!oldsbsec->initialized); | ||
| 765 | |||
| 766 | mutex_lock(&newsbsec->lock); | ||
| 767 | |||
| 768 | newsbsec->flags = oldsbsec->flags; | ||
| 769 | |||
| 770 | newsbsec->sid = oldsbsec->sid; | ||
| 771 | newsbsec->def_sid = oldsbsec->def_sid; | ||
| 772 | newsbsec->behavior = oldsbsec->behavior; | ||
| 773 | |||
| 774 | if (set_context) { | ||
| 775 | u32 sid = oldsbsec->mntpoint_sid; | ||
| 776 | |||
| 777 | if (!set_fscontext) | ||
| 778 | newsbsec->sid = sid; | ||
| 779 | if (!set_rootcontext) { | ||
| 780 | struct inode *newinode = newsb->s_root->d_inode; | ||
| 781 | struct inode_security_struct *newisec = newinode->i_security; | ||
| 782 | newisec->sid = sid; | ||
| 783 | } | ||
| 784 | newsbsec->mntpoint_sid = sid; | ||
| 613 | } | 785 | } |
| 786 | if (set_rootcontext) { | ||
| 787 | const struct inode *oldinode = oldsb->s_root->d_inode; | ||
| 788 | const struct inode_security_struct *oldisec = oldinode->i_security; | ||
| 789 | struct inode *newinode = newsb->s_root->d_inode; | ||
| 790 | struct inode_security_struct *newisec = newinode->i_security; | ||
| 614 | 791 | ||
| 615 | /* Determine the labeling behavior to use for this filesystem type. */ | 792 | newisec->sid = oldisec->sid; |
| 616 | rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid); | ||
| 617 | if (rc) { | ||
| 618 | printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n", | ||
| 619 | __FUNCTION__, sb->s_type->name, rc); | ||
| 620 | goto out; | ||
| 621 | } | 793 | } |
| 622 | 794 | ||
| 623 | rc = try_context_mount(sb, data); | 795 | sb_finish_set_opts(newsb); |
| 624 | if (rc) | 796 | mutex_unlock(&newsbsec->lock); |
| 797 | } | ||
| 798 | |||
| 799 | /* | ||
| 800 | * string mount options parsing and call set the sbsec | ||
| 801 | */ | ||
| 802 | static int superblock_doinit(struct super_block *sb, void *data) | ||
| 803 | { | ||
| 804 | char *context = NULL, *defcontext = NULL; | ||
| 805 | char *fscontext = NULL, *rootcontext = NULL; | ||
| 806 | int rc = 0; | ||
| 807 | char *p, *options = data; | ||
| 808 | /* selinux only know about a fixed number of mount options */ | ||
| 809 | char *mnt_opts[NUM_SEL_MNT_OPTS]; | ||
| 810 | int mnt_opts_flags[NUM_SEL_MNT_OPTS], num_mnt_opts = 0; | ||
| 811 | |||
| 812 | if (!data) | ||
| 625 | goto out; | 813 | goto out; |
| 626 | 814 | ||
| 627 | if (sbsec->behavior == SECURITY_FS_USE_XATTR) { | 815 | /* with the nfs patch this will become a goto out; */ |
| 628 | /* Make sure that the xattr handler exists and that no | 816 | if (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA) { |
| 629 | error other than -ENODATA is returned by getxattr on | 817 | const char *name = sb->s_type->name; |
| 630 | the root directory. -ENODATA is ok, as this may be | 818 | /* NFS we understand. */ |
| 631 | the first boot of the SELinux kernel before we have | 819 | if (!strcmp(name, "nfs")) { |
| 632 | assigned xattr values to the filesystem. */ | 820 | struct nfs_mount_data *d = data; |
| 633 | if (!inode->i_op->getxattr) { | 821 | |
| 634 | printk(KERN_WARNING "SELinux: (dev %s, type %s) has no " | 822 | if (d->version != NFS_MOUNT_VERSION) |
| 635 | "xattr support\n", sb->s_id, sb->s_type->name); | 823 | goto out; |
| 636 | rc = -EOPNOTSUPP; | 824 | |
| 637 | goto out; | 825 | if (d->context[0]) { |
| 638 | } | 826 | context = kstrdup(d->context, GFP_KERNEL); |
| 639 | rc = inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0); | 827 | if (!context) { |
| 640 | if (rc < 0 && rc != -ENODATA) { | 828 | rc = -ENOMEM; |
| 641 | if (rc == -EOPNOTSUPP) | 829 | goto out; |
| 642 | printk(KERN_WARNING "SELinux: (dev %s, type " | 830 | } |
| 643 | "%s) has no security xattr handler\n", | 831 | } |
| 644 | sb->s_id, sb->s_type->name); | 832 | goto build_flags; |
| 645 | else | 833 | } else |
| 646 | printk(KERN_WARNING "SELinux: (dev %s, type " | ||
| 647 | "%s) getxattr errno %d\n", sb->s_id, | ||
| 648 | sb->s_type->name, -rc); | ||
| 649 | goto out; | 834 | goto out; |
| 650 | } | ||
| 651 | } | 835 | } |
| 652 | 836 | ||
| 653 | if (strcmp(sb->s_type->name, "proc") == 0) | 837 | /* Standard string-based options. */ |
| 654 | sbsec->proc = 1; | 838 | while ((p = strsep(&options, "|")) != NULL) { |
| 839 | int token; | ||
| 840 | substring_t args[MAX_OPT_ARGS]; | ||
| 655 | 841 | ||
| 656 | sbsec->initialized = 1; | 842 | if (!*p) |
| 843 | continue; | ||
| 657 | 844 | ||
| 658 | if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) { | 845 | token = match_token(p, tokens, args); |
| 659 | printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", | ||
| 660 | sb->s_id, sb->s_type->name); | ||
| 661 | } | ||
| 662 | else { | ||
| 663 | printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n", | ||
| 664 | sb->s_id, sb->s_type->name, | ||
| 665 | labeling_behaviors[sbsec->behavior-1]); | ||
| 666 | } | ||
| 667 | 846 | ||
| 668 | /* Initialize the root inode. */ | 847 | switch (token) { |
| 669 | rc = inode_doinit_with_dentry(sb->s_root->d_inode, sb->s_root); | 848 | case Opt_context: |
| 849 | if (context || defcontext) { | ||
| 850 | rc = -EINVAL; | ||
| 851 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | ||
| 852 | goto out_err; | ||
| 853 | } | ||
| 854 | context = match_strdup(&args[0]); | ||
| 855 | if (!context) { | ||
| 856 | rc = -ENOMEM; | ||
| 857 | goto out_err; | ||
| 858 | } | ||
| 859 | break; | ||
| 860 | |||
| 861 | case Opt_fscontext: | ||
| 862 | if (fscontext) { | ||
| 863 | rc = -EINVAL; | ||
| 864 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | ||
| 865 | goto out_err; | ||
| 866 | } | ||
| 867 | fscontext = match_strdup(&args[0]); | ||
| 868 | if (!fscontext) { | ||
| 869 | rc = -ENOMEM; | ||
| 870 | goto out_err; | ||
| 871 | } | ||
| 872 | break; | ||
| 873 | |||
| 874 | case Opt_rootcontext: | ||
| 875 | if (rootcontext) { | ||
| 876 | rc = -EINVAL; | ||
| 877 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | ||
| 878 | goto out_err; | ||
| 879 | } | ||
| 880 | rootcontext = match_strdup(&args[0]); | ||
| 881 | if (!rootcontext) { | ||
| 882 | rc = -ENOMEM; | ||
| 883 | goto out_err; | ||
| 884 | } | ||
| 885 | break; | ||
| 886 | |||
| 887 | case Opt_defcontext: | ||
| 888 | if (context || defcontext) { | ||
| 889 | rc = -EINVAL; | ||
| 890 | printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); | ||
| 891 | goto out_err; | ||
| 892 | } | ||
| 893 | defcontext = match_strdup(&args[0]); | ||
| 894 | if (!defcontext) { | ||
| 895 | rc = -ENOMEM; | ||
| 896 | goto out_err; | ||
| 897 | } | ||
| 898 | break; | ||
| 899 | |||
| 900 | default: | ||
| 901 | rc = -EINVAL; | ||
| 902 | printk(KERN_WARNING "SELinux: unknown mount option\n"); | ||
| 903 | goto out_err; | ||
| 670 | 904 | ||
| 671 | /* Initialize any other inodes associated with the superblock, e.g. | ||
| 672 | inodes created prior to initial policy load or inodes created | ||
| 673 | during get_sb by a pseudo filesystem that directly | ||
| 674 | populates itself. */ | ||
| 675 | spin_lock(&sbsec->isec_lock); | ||
| 676 | next_inode: | ||
| 677 | if (!list_empty(&sbsec->isec_head)) { | ||
| 678 | struct inode_security_struct *isec = | ||
| 679 | list_entry(sbsec->isec_head.next, | ||
| 680 | struct inode_security_struct, list); | ||
| 681 | struct inode *inode = isec->inode; | ||
| 682 | spin_unlock(&sbsec->isec_lock); | ||
| 683 | inode = igrab(inode); | ||
| 684 | if (inode) { | ||
| 685 | if (!IS_PRIVATE (inode)) | ||
| 686 | inode_doinit(inode); | ||
| 687 | iput(inode); | ||
| 688 | } | 905 | } |
| 689 | spin_lock(&sbsec->isec_lock); | ||
| 690 | list_del_init(&isec->list); | ||
| 691 | goto next_inode; | ||
| 692 | } | 906 | } |
| 693 | spin_unlock(&sbsec->isec_lock); | 907 | |
| 908 | build_flags: | ||
| 909 | if (fscontext) { | ||
| 910 | mnt_opts[num_mnt_opts] = fscontext; | ||
| 911 | mnt_opts_flags[num_mnt_opts++] = FSCONTEXT_MNT; | ||
| 912 | } | ||
| 913 | if (context) { | ||
| 914 | mnt_opts[num_mnt_opts] = context; | ||
| 915 | mnt_opts_flags[num_mnt_opts++] = CONTEXT_MNT; | ||
| 916 | } | ||
| 917 | if (rootcontext) { | ||
| 918 | mnt_opts[num_mnt_opts] = rootcontext; | ||
| 919 | mnt_opts_flags[num_mnt_opts++] = ROOTCONTEXT_MNT; | ||
| 920 | } | ||
| 921 | if (defcontext) { | ||
| 922 | mnt_opts[num_mnt_opts] = defcontext; | ||
| 923 | mnt_opts_flags[num_mnt_opts++] = DEFCONTEXT_MNT; | ||
| 924 | } | ||
| 925 | |||
| 694 | out: | 926 | out: |
| 695 | mutex_unlock(&sbsec->lock); | 927 | rc = selinux_set_mnt_opts(sb, mnt_opts, mnt_opts_flags, num_mnt_opts); |
| 928 | out_err: | ||
| 929 | kfree(context); | ||
| 930 | kfree(defcontext); | ||
| 931 | kfree(fscontext); | ||
| 932 | kfree(rootcontext); | ||
| 696 | return rc; | 933 | return rc; |
| 697 | } | 934 | } |
| 698 | 935 | ||
| @@ -4710,6 +4947,11 @@ static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | |||
| 4710 | return security_sid_to_context(secid, secdata, seclen); | 4947 | return security_sid_to_context(secid, secdata, seclen); |
| 4711 | } | 4948 | } |
| 4712 | 4949 | ||
| 4950 | static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid) | ||
| 4951 | { | ||
| 4952 | return security_context_to_sid(secdata, seclen, secid); | ||
| 4953 | } | ||
| 4954 | |||
| 4713 | static void selinux_release_secctx(char *secdata, u32 seclen) | 4955 | static void selinux_release_secctx(char *secdata, u32 seclen) |
| 4714 | { | 4956 | { |
| 4715 | kfree(secdata); | 4957 | kfree(secdata); |
| @@ -4800,6 +5042,9 @@ static struct security_operations selinux_ops = { | |||
| 4800 | .sb_statfs = selinux_sb_statfs, | 5042 | .sb_statfs = selinux_sb_statfs, |
| 4801 | .sb_mount = selinux_mount, | 5043 | .sb_mount = selinux_mount, |
| 4802 | .sb_umount = selinux_umount, | 5044 | .sb_umount = selinux_umount, |
| 5045 | .sb_get_mnt_opts = selinux_get_mnt_opts, | ||
| 5046 | .sb_set_mnt_opts = selinux_set_mnt_opts, | ||
| 5047 | .sb_clone_mnt_opts = selinux_sb_clone_mnt_opts, | ||
| 4803 | 5048 | ||
| 4804 | .inode_alloc_security = selinux_inode_alloc_security, | 5049 | .inode_alloc_security = selinux_inode_alloc_security, |
| 4805 | .inode_free_security = selinux_inode_free_security, | 5050 | .inode_free_security = selinux_inode_free_security, |
| @@ -4898,6 +5143,7 @@ static struct security_operations selinux_ops = { | |||
| 4898 | .setprocattr = selinux_setprocattr, | 5143 | .setprocattr = selinux_setprocattr, |
| 4899 | 5144 | ||
| 4900 | .secid_to_secctx = selinux_secid_to_secctx, | 5145 | .secid_to_secctx = selinux_secid_to_secctx, |
| 5146 | .secctx_to_secid = selinux_secctx_to_secid, | ||
| 4901 | .release_secctx = selinux_release_secctx, | 5147 | .release_secctx = selinux_release_secctx, |
| 4902 | 5148 | ||
| 4903 | .unix_stream_connect = selinux_socket_unix_stream_connect, | 5149 | .unix_stream_connect = selinux_socket_unix_stream_connect, |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 642a9fd319ad..4138a80f8e27 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
| @@ -65,6 +65,7 @@ struct superblock_security_struct { | |||
| 65 | u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */ | 65 | u32 mntpoint_sid; /* SECURITY_FS_USE_MNTPOINT context for files */ |
| 66 | unsigned int behavior; /* labeling behavior */ | 66 | unsigned int behavior; /* labeling behavior */ |
| 67 | unsigned char initialized; /* initialization flag */ | 67 | unsigned char initialized; /* initialization flag */ |
| 68 | unsigned char flags; /* which mount options were specified */ | ||
| 68 | unsigned char proc; /* proc fs */ | 69 | unsigned char proc; /* proc fs */ |
| 69 | struct mutex lock; | 70 | struct mutex lock; |
| 70 | struct list_head isec_head; | 71 | struct list_head isec_head; |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 2fa483f26113..397fd4955fe1 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
| @@ -1222,7 +1222,7 @@ static int sel_avc_stats_seq_show(struct seq_file *seq, void *v) | |||
| 1222 | static void sel_avc_stats_seq_stop(struct seq_file *seq, void *v) | 1222 | static void sel_avc_stats_seq_stop(struct seq_file *seq, void *v) |
| 1223 | { } | 1223 | { } |
| 1224 | 1224 | ||
| 1225 | static struct seq_operations sel_avc_cache_stats_seq_ops = { | 1225 | static const struct seq_operations sel_avc_cache_stats_seq_ops = { |
| 1226 | .start = sel_avc_stats_seq_start, | 1226 | .start = sel_avc_stats_seq_start, |
| 1227 | .next = sel_avc_stats_seq_next, | 1227 | .next = sel_avc_stats_seq_next, |
| 1228 | .show = sel_avc_stats_seq_show, | 1228 | .show = sel_avc_stats_seq_show, |
diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 9e70a160d7da..cd10e27fc9e6 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c | |||
| @@ -280,7 +280,7 @@ int avtab_alloc(struct avtab *h, u32 nrules) | |||
| 280 | h->nel = 0; | 280 | h->nel = 0; |
| 281 | h->nslot = nslot; | 281 | h->nslot = nslot; |
| 282 | h->mask = mask; | 282 | h->mask = mask; |
| 283 | printk(KERN_DEBUG "SELinux:%d avtab hash slots allocated." | 283 | printk(KERN_DEBUG "SELinux:%d avtab hash slots allocated. " |
| 284 | "Num of rules:%d\n", h->nslot, nrules); | 284 | "Num of rules:%d\n", h->nslot, nrules); |
| 285 | return 0; | 285 | return 0; |
| 286 | } | 286 | } |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index fb5d70a6628d..3bbcb5369af9 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
| @@ -537,15 +537,8 @@ int mls_compute_sid(struct context *scontext, | |||
| 537 | /* Use the process effective MLS attributes. */ | 537 | /* Use the process effective MLS attributes. */ |
| 538 | return mls_context_cpy_low(newcontext, scontext); | 538 | return mls_context_cpy_low(newcontext, scontext); |
| 539 | case AVTAB_MEMBER: | 539 | case AVTAB_MEMBER: |
| 540 | /* Only polyinstantiate the MLS attributes if | 540 | /* Use the process effective MLS attributes. */ |
| 541 | the type is being polyinstantiated */ | 541 | return mls_context_cpy_low(newcontext, scontext); |
| 542 | if (newcontext->type != tcontext->type) { | ||
| 543 | /* Use the process effective MLS attributes. */ | ||
| 544 | return mls_context_cpy_low(newcontext, scontext); | ||
| 545 | } else { | ||
| 546 | /* Use the related object MLS attributes. */ | ||
| 547 | return mls_context_cpy(newcontext, tcontext); | ||
| 548 | } | ||
| 549 | default: | 542 | default: |
| 550 | return -EINVAL; | 543 | return -EINVAL; |
| 551 | } | 544 | } |
