aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-01-25 11:44:29 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2008-01-25 11:44:29 -0500
commitb47711bfbcd4eb77ca61ef0162487b20e023ae55 (patch)
treeb2a695dbd40f7ca2333664cf946ef34eda7b7dba
parent7556afa0e0e436cad4f560ee83e5fbd5dac9359a (diff)
parent2e08c0c1c3977a5ddc88887dd3af1b26c433e9d0 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6: selinux: make mls_compute_sid always polyinstantiate security/selinux: constify function pointer tables and fields security: add a secctx_to_secid() hook security: call security_file_permission from rw_verify_area security: remove security_sb_post_mountroot hook Security: remove security.h include from mm.h Security: remove security_file_mmap hook sparse-warnings (NULL as 0). Security: add get, set, and cloning of superblock security information security/selinux: Add missing "space"
-rw-r--r--fs/compat.c4
-rw-r--r--fs/read_write.c63
-rw-r--r--fs/splice.c8
-rw-r--r--include/linux/mm.h3
-rw-r--r--include/linux/security.h59
-rw-r--r--init/do_mounts.c1
-rw-r--r--mm/mmap.c4
-rw-r--r--security/dummy.c36
-rw-r--r--security/keys/proc.c4
-rw-r--r--security/security.c31
-rw-r--r--security/selinux/hooks.c754
-rw-r--r--security/selinux/include/objsec.h1
-rw-r--r--security/selinux/selinuxfs.c2
-rw-r--r--security/selinux/ss/avtab.c2
-rw-r--r--security/selinux/ss/mls.c11
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
217Einval:
218 return -EINVAL;
219} 221}
220 222
221static void wait_on_retry_sync_kiocb(struct kiocb *iocb) 223static 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
17struct mempolicy; 16struct mempolicy;
18struct anon_vma; 17struct 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
36extern 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);
1495void security_sb_umount_close(struct vfsmount *mnt); 1525void security_sb_umount_close(struct vfsmount *mnt);
1496void security_sb_umount_busy(struct vfsmount *mnt); 1526void security_sb_umount_busy(struct vfsmount *mnt);
1497void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data); 1527void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *data);
1498void security_sb_post_mountroot(void);
1499void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd); 1528void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd);
1500int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd); 1529int security_sb_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd);
1501void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd); 1530void security_sb_post_pivotroot(struct nameidata *old_nd, struct nameidata *new_nd);
1531int security_sb_get_mnt_opts(const struct super_block *sb, char ***mount_options,
1532 int **flags, int *num_opts);
1533int security_sb_set_mnt_opts(struct super_block *sb, char **mount_options,
1534 int *flags, int num_opts);
1535void security_sb_clone_mnt_opts(const struct super_block *oldsb,
1536 struct super_block *newsb);
1537
1502int security_inode_alloc(struct inode *inode); 1538int security_inode_alloc(struct inode *inode);
1503void security_inode_free(struct inode *inode); 1539void security_inode_free(struct inode *inode);
1504int security_inode_init_security(struct inode *inode, struct inode *dir, 1540int 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
1603int security_netlink_send(struct sock *sk, struct sk_buff *skb); 1639int security_netlink_send(struct sock *sk, struct sk_buff *skb);
1604int security_netlink_recv(struct sk_buff *skb, int cap); 1640int security_netlink_recv(struct sk_buff *skb, int cap);
1605int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); 1641int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
1642int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid);
1606void security_release_secctx(char *secdata, u32 seclen); 1643void 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
1780static inline void security_sb_post_mountroot (void)
1781{ }
1782
1783static inline void security_sb_post_addmount (struct vfsmount *mnt, 1817static 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
2317static inline int security_secctx_to_secid(char *secdata,
2318 u32 seclen,
2319 u32 *secid)
2320{
2321 return -EOPNOTSUPP;
2322}
2323
2283static inline void security_release_secctx(char *secdata, u32 seclen) 2324static 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)
378out: 378out:
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
diff --git a/mm/mmap.c b/mm/mmap.c
index 15678aa6ec73..bfa389fc6ded 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -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
228static void dummy_sb_post_mountroot (void) 228static void dummy_sb_post_addmount (struct vfsmount *mnt, struct nameidata *nd)
229{ 229{
230 return; 230 return;
231} 231}
232 232
233static void dummy_sb_post_addmount (struct vfsmount *mnt, struct nameidata *nd) 233static int dummy_sb_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd)
234{
235 return 0;
236}
237
238static void dummy_sb_post_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd)
234{ 239{
235 return; 240 return;
236} 241}
237 242
238static int dummy_sb_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd) 243static 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
243static void dummy_sb_post_pivotroot (struct nameidata *old_nd, struct nameidata *new_nd) 252static 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
260static 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
949static int dummy_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
950{
951 return -EOPNOTSUPP;
952}
953
931static void dummy_release_secctx(char *secdata, u32 seclen) 954static 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);
26static void proc_keys_stop(struct seq_file *p, void *v); 26static void proc_keys_stop(struct seq_file *p, void *v);
27static int proc_keys_show(struct seq_file *m, void *v); 27static int proc_keys_show(struct seq_file *m, void *v);
28 28
29static struct seq_operations proc_keys_ops = { 29static 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);
47static void proc_key_users_stop(struct seq_file *p, void *v); 47static void proc_key_users_stop(struct seq_file *p, void *v);
48static int proc_key_users_show(struct seq_file *m, void *v); 48static int proc_key_users_show(struct seq_file *m, void *v);
49 49
50static struct seq_operations proc_key_users_ops = { 50static 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
291void security_sb_post_mountroot(void)
292{
293 security_ops->sb_post_mountroot();
294}
295
296void security_sb_post_addmount(struct vfsmount *mnt, struct nameidata *mountpoint_nd) 291void 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
306int 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
313int 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
320void 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
311int security_inode_alloc(struct inode *inode) 326int 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}
817EXPORT_SYMBOL(security_secid_to_secctx); 832EXPORT_SYMBOL(security_secid_to_secctx);
818 833
834int security_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
835{
836 return security_ops->secctx_to_secid(secdata, seclen, secid);
837}
838EXPORT_SYMBOL(security_secctx_to_secid);
839
819void security_release_secctx(char *secdata, u32 seclen) 840void 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
85extern unsigned int policydb_loaded_version; 87extern unsigned int policydb_loaded_version;
86extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); 88extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
87extern int selinux_compat_net; 89extern 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
328static match_table_t tokens = { 330static 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
369static int try_context_mount(struct super_block *sb, void *data) 371static 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);
422next_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);
440out:
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; 449static 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 } 530out_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
543static 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 */
564int 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
582out_free: 734 rc = sb_finish_set_opts(sb);
583 if (alloc) {
584 kfree(context);
585 kfree(defcontext);
586 kfree(fscontext);
587 kfree(rootcontext);
588 }
589out: 735out:
736 mutex_unlock(&sbsec->lock);
590 return rc; 737 return rc;
738out_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
593static int superblock_doinit(struct super_block *sb, void *data) 745static 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 */
802static 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);
676next_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
908build_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
694out: 926out:
695 mutex_unlock(&sbsec->lock); 927 rc = selinux_set_mnt_opts(sb, mnt_opts, mnt_opts_flags, num_mnt_opts);
928out_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
4950static int selinux_secctx_to_secid(char *secdata, u32 seclen, u32 *secid)
4951{
4952 return security_context_to_sid(secdata, seclen, secid);
4953}
4954
4713static void selinux_release_secctx(char *secdata, u32 seclen) 4955static 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)
1222static void sel_avc_stats_seq_stop(struct seq_file *seq, void *v) 1222static void sel_avc_stats_seq_stop(struct seq_file *seq, void *v)
1223{ } 1223{ }
1224 1224
1225static struct seq_operations sel_avc_cache_stats_seq_ops = { 1225static 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 }