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 | } |