diff options
-rw-r--r-- | fs/btrfs/super.c | 10 | ||||
-rw-r--r-- | fs/namespace.c | 9 | ||||
-rw-r--r-- | fs/nfs/internal.h | 2 | ||||
-rw-r--r-- | fs/nfs/super.c | 6 | ||||
-rw-r--r-- | fs/super.c | 12 | ||||
-rw-r--r-- | include/linux/lsm_hooks.h | 11 | ||||
-rw-r--r-- | include/linux/security.h | 43 | ||||
-rw-r--r-- | security/security.c | 27 | ||||
-rw-r--r-- | security/selinux/hooks.c | 52 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 38 |
10 files changed, 118 insertions, 92 deletions
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 3b04e7735b5f..e90c4616ed6a 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -1472,14 +1472,13 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type, | |||
1472 | struct btrfs_device *device = NULL; | 1472 | struct btrfs_device *device = NULL; |
1473 | struct btrfs_fs_devices *fs_devices = NULL; | 1473 | struct btrfs_fs_devices *fs_devices = NULL; |
1474 | struct btrfs_fs_info *fs_info = NULL; | 1474 | struct btrfs_fs_info *fs_info = NULL; |
1475 | struct security_mnt_opts new_sec_opts; | 1475 | void *new_sec_opts = NULL; |
1476 | fmode_t mode = FMODE_READ; | 1476 | fmode_t mode = FMODE_READ; |
1477 | int error = 0; | 1477 | int error = 0; |
1478 | 1478 | ||
1479 | if (!(flags & SB_RDONLY)) | 1479 | if (!(flags & SB_RDONLY)) |
1480 | mode |= FMODE_WRITE; | 1480 | mode |= FMODE_WRITE; |
1481 | 1481 | ||
1482 | security_init_mnt_opts(&new_sec_opts); | ||
1483 | if (data) { | 1482 | if (data) { |
1484 | error = security_sb_eat_lsm_opts(data, &new_sec_opts); | 1483 | error = security_sb_eat_lsm_opts(data, &new_sec_opts); |
1485 | if (error) | 1484 | if (error) |
@@ -1551,7 +1550,7 @@ static struct dentry *btrfs_mount_root(struct file_system_type *fs_type, | |||
1551 | error = btrfs_fill_super(s, fs_devices, data); | 1550 | error = btrfs_fill_super(s, fs_devices, data); |
1552 | } | 1551 | } |
1553 | if (!error) | 1552 | if (!error) |
1554 | error = security_sb_set_mnt_opts(s, &new_sec_opts, 0, NULL); | 1553 | error = security_sb_set_mnt_opts(s, new_sec_opts, 0, NULL); |
1555 | security_free_mnt_opts(&new_sec_opts); | 1554 | security_free_mnt_opts(&new_sec_opts); |
1556 | if (error) { | 1555 | if (error) { |
1557 | deactivate_locked_super(s); | 1556 | deactivate_locked_super(s); |
@@ -1724,12 +1723,11 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data) | |||
1724 | btrfs_remount_prepare(fs_info); | 1723 | btrfs_remount_prepare(fs_info); |
1725 | 1724 | ||
1726 | if (data) { | 1725 | if (data) { |
1727 | struct security_mnt_opts new_sec_opts; | 1726 | void *new_sec_opts = NULL; |
1728 | 1727 | ||
1729 | security_init_mnt_opts(&new_sec_opts); | ||
1730 | ret = security_sb_eat_lsm_opts(data, &new_sec_opts); | 1728 | ret = security_sb_eat_lsm_opts(data, &new_sec_opts); |
1731 | if (!ret) | 1729 | if (!ret) |
1732 | ret = security_sb_remount(sb, &new_sec_opts); | 1730 | ret = security_sb_remount(sb, new_sec_opts); |
1733 | security_free_mnt_opts(&new_sec_opts); | 1731 | security_free_mnt_opts(&new_sec_opts); |
1734 | if (ret) | 1732 | if (ret) |
1735 | goto restore; | 1733 | goto restore; |
diff --git a/fs/namespace.c b/fs/namespace.c index 39aca7b69c2e..badfd287358c 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -2299,7 +2299,7 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags, | |||
2299 | int err; | 2299 | int err; |
2300 | struct super_block *sb = path->mnt->mnt_sb; | 2300 | struct super_block *sb = path->mnt->mnt_sb; |
2301 | struct mount *mnt = real_mount(path->mnt); | 2301 | struct mount *mnt = real_mount(path->mnt); |
2302 | struct security_mnt_opts opts; | 2302 | void *sec_opts = NULL; |
2303 | 2303 | ||
2304 | if (!check_mnt(mnt)) | 2304 | if (!check_mnt(mnt)) |
2305 | return -EINVAL; | 2305 | return -EINVAL; |
@@ -2310,14 +2310,13 @@ static int do_remount(struct path *path, int ms_flags, int sb_flags, | |||
2310 | if (!can_change_locked_flags(mnt, mnt_flags)) | 2310 | if (!can_change_locked_flags(mnt, mnt_flags)) |
2311 | return -EPERM; | 2311 | return -EPERM; |
2312 | 2312 | ||
2313 | security_init_mnt_opts(&opts); | ||
2314 | if (data && !(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)) { | 2313 | if (data && !(sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)) { |
2315 | err = security_sb_eat_lsm_opts(data, &opts); | 2314 | err = security_sb_eat_lsm_opts(data, &sec_opts); |
2316 | if (err) | 2315 | if (err) |
2317 | return err; | 2316 | return err; |
2318 | } | 2317 | } |
2319 | err = security_sb_remount(sb, &opts); | 2318 | err = security_sb_remount(sb, sec_opts); |
2320 | security_free_mnt_opts(&opts); | 2319 | security_free_mnt_opts(&sec_opts); |
2321 | if (err) | 2320 | if (err) |
2322 | return err; | 2321 | return err; |
2323 | 2322 | ||
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index 8357ff69962f..97e1dcefe561 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
@@ -123,7 +123,7 @@ struct nfs_parsed_mount_data { | |||
123 | unsigned short protocol; | 123 | unsigned short protocol; |
124 | } nfs_server; | 124 | } nfs_server; |
125 | 125 | ||
126 | struct security_mnt_opts lsm_opts; | 126 | void *lsm_opts; |
127 | struct net *net; | 127 | struct net *net; |
128 | }; | 128 | }; |
129 | 129 | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 300bdd1d4a09..1943de8f9d29 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -929,7 +929,7 @@ static struct nfs_parsed_mount_data *nfs_alloc_parsed_mount_data(void) | |||
929 | data->minorversion = 0; | 929 | data->minorversion = 0; |
930 | data->need_mount = true; | 930 | data->need_mount = true; |
931 | data->net = current->nsproxy->net_ns; | 931 | data->net = current->nsproxy->net_ns; |
932 | security_init_mnt_opts(&data->lsm_opts); | 932 | data->lsm_opts = NULL; |
933 | } | 933 | } |
934 | return data; | 934 | return data; |
935 | } | 935 | } |
@@ -2294,7 +2294,7 @@ nfs_remount(struct super_block *sb, int *flags, char *raw_data) | |||
2294 | /* compare new mount options with old ones */ | 2294 | /* compare new mount options with old ones */ |
2295 | error = nfs_compare_remount_data(nfss, data); | 2295 | error = nfs_compare_remount_data(nfss, data); |
2296 | if (!error) | 2296 | if (!error) |
2297 | error = security_sb_remount(sb, &data->lsm_opts); | 2297 | error = security_sb_remount(sb, data->lsm_opts); |
2298 | out: | 2298 | out: |
2299 | nfs_free_parsed_mount_data(data); | 2299 | nfs_free_parsed_mount_data(data); |
2300 | return error; | 2300 | return error; |
@@ -2534,7 +2534,7 @@ int nfs_set_sb_security(struct super_block *s, struct dentry *mntroot, | |||
2534 | if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL) | 2534 | if (NFS_SB(s)->caps & NFS_CAP_SECURITY_LABEL) |
2535 | kflags |= SECURITY_LSM_NATIVE_LABELS; | 2535 | kflags |= SECURITY_LSM_NATIVE_LABELS; |
2536 | 2536 | ||
2537 | error = security_sb_set_mnt_opts(s, &mount_info->parsed->lsm_opts, | 2537 | error = security_sb_set_mnt_opts(s, mount_info->parsed->lsm_opts, |
2538 | kflags, &kflags_out); | 2538 | kflags, &kflags_out); |
2539 | if (error) | 2539 | if (error) |
2540 | goto err; | 2540 | goto err; |
diff --git a/fs/super.c b/fs/super.c index 1f75fe312597..a5511c4ba69b 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -1247,12 +1247,10 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data) | |||
1247 | struct dentry *root; | 1247 | struct dentry *root; |
1248 | struct super_block *sb; | 1248 | struct super_block *sb; |
1249 | int error = -ENOMEM; | 1249 | int error = -ENOMEM; |
1250 | struct security_mnt_opts opts; | 1250 | void *sec_opts = NULL; |
1251 | |||
1252 | security_init_mnt_opts(&opts); | ||
1253 | 1251 | ||
1254 | if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { | 1252 | if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { |
1255 | error = security_sb_eat_lsm_opts(data, &opts); | 1253 | error = security_sb_eat_lsm_opts(data, &sec_opts); |
1256 | if (error) | 1254 | if (error) |
1257 | return ERR_PTR(error); | 1255 | return ERR_PTR(error); |
1258 | } | 1256 | } |
@@ -1275,7 +1273,7 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data) | |||
1275 | smp_wmb(); | 1273 | smp_wmb(); |
1276 | sb->s_flags |= SB_BORN; | 1274 | sb->s_flags |= SB_BORN; |
1277 | 1275 | ||
1278 | error = security_sb_set_mnt_opts(sb, &opts, 0, NULL); | 1276 | error = security_sb_set_mnt_opts(sb, sec_opts, 0, NULL); |
1279 | if (error) | 1277 | if (error) |
1280 | goto out_sb; | 1278 | goto out_sb; |
1281 | 1279 | ||
@@ -1295,13 +1293,13 @@ mount_fs(struct file_system_type *type, int flags, const char *name, void *data) | |||
1295 | "negative value (%lld)\n", type->name, sb->s_maxbytes); | 1293 | "negative value (%lld)\n", type->name, sb->s_maxbytes); |
1296 | 1294 | ||
1297 | up_write(&sb->s_umount); | 1295 | up_write(&sb->s_umount); |
1298 | security_free_mnt_opts(&opts); | 1296 | security_free_mnt_opts(&sec_opts); |
1299 | return root; | 1297 | return root; |
1300 | out_sb: | 1298 | out_sb: |
1301 | dput(root); | 1299 | dput(root); |
1302 | deactivate_locked_super(sb); | 1300 | deactivate_locked_super(sb); |
1303 | out_free_secdata: | 1301 | out_free_secdata: |
1304 | security_free_mnt_opts(&opts); | 1302 | security_free_mnt_opts(&sec_opts); |
1305 | return ERR_PTR(error); | 1303 | return ERR_PTR(error); |
1306 | } | 1304 | } |
1307 | 1305 | ||
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index c418909c178c..a9c541f5732e 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h | |||
@@ -1461,9 +1461,9 @@ union security_list_options { | |||
1461 | 1461 | ||
1462 | int (*sb_alloc_security)(struct super_block *sb); | 1462 | int (*sb_alloc_security)(struct super_block *sb); |
1463 | void (*sb_free_security)(struct super_block *sb); | 1463 | void (*sb_free_security)(struct super_block *sb); |
1464 | int (*sb_eat_lsm_opts)(char *orig, struct security_mnt_opts *opts); | 1464 | void (*sb_free_mnt_opts)(void *mnt_opts); |
1465 | int (*sb_remount)(struct super_block *sb, | 1465 | int (*sb_eat_lsm_opts)(char *orig, void **mnt_opts); |
1466 | struct security_mnt_opts *opts); | 1466 | int (*sb_remount)(struct super_block *sb, void *mnt_opts); |
1467 | int (*sb_kern_mount)(struct super_block *sb); | 1467 | int (*sb_kern_mount)(struct super_block *sb); |
1468 | int (*sb_show_options)(struct seq_file *m, struct super_block *sb); | 1468 | int (*sb_show_options)(struct seq_file *m, struct super_block *sb); |
1469 | int (*sb_statfs)(struct dentry *dentry); | 1469 | int (*sb_statfs)(struct dentry *dentry); |
@@ -1472,14 +1472,14 @@ union security_list_options { | |||
1472 | int (*sb_umount)(struct vfsmount *mnt, int flags); | 1472 | int (*sb_umount)(struct vfsmount *mnt, int flags); |
1473 | int (*sb_pivotroot)(const struct path *old_path, const struct path *new_path); | 1473 | int (*sb_pivotroot)(const struct path *old_path, const struct path *new_path); |
1474 | int (*sb_set_mnt_opts)(struct super_block *sb, | 1474 | int (*sb_set_mnt_opts)(struct super_block *sb, |
1475 | struct security_mnt_opts *opts, | 1475 | void *mnt_opts, |
1476 | unsigned long kern_flags, | 1476 | unsigned long kern_flags, |
1477 | unsigned long *set_kern_flags); | 1477 | unsigned long *set_kern_flags); |
1478 | int (*sb_clone_mnt_opts)(const struct super_block *oldsb, | 1478 | int (*sb_clone_mnt_opts)(const struct super_block *oldsb, |
1479 | struct super_block *newsb, | 1479 | struct super_block *newsb, |
1480 | unsigned long kern_flags, | 1480 | unsigned long kern_flags, |
1481 | unsigned long *set_kern_flags); | 1481 | unsigned long *set_kern_flags); |
1482 | int (*sb_parse_opts_str)(char *options, struct security_mnt_opts *opts); | 1482 | int (*sb_parse_opts_str)(char *options, void **mnt_opts); |
1483 | int (*dentry_init_security)(struct dentry *dentry, int mode, | 1483 | int (*dentry_init_security)(struct dentry *dentry, int mode, |
1484 | const struct qstr *name, void **ctx, | 1484 | const struct qstr *name, void **ctx, |
1485 | u32 *ctxlen); | 1485 | u32 *ctxlen); |
@@ -1801,6 +1801,7 @@ struct security_hook_heads { | |||
1801 | struct hlist_head bprm_committed_creds; | 1801 | struct hlist_head bprm_committed_creds; |
1802 | struct hlist_head sb_alloc_security; | 1802 | struct hlist_head sb_alloc_security; |
1803 | struct hlist_head sb_free_security; | 1803 | struct hlist_head sb_free_security; |
1804 | struct hlist_head sb_free_mnt_opts; | ||
1804 | struct hlist_head sb_eat_lsm_opts; | 1805 | struct hlist_head sb_eat_lsm_opts; |
1805 | struct hlist_head sb_remount; | 1806 | struct hlist_head sb_remount; |
1806 | struct hlist_head sb_kern_mount; | 1807 | struct hlist_head sb_kern_mount; |
diff --git a/include/linux/security.h b/include/linux/security.h index d00093363570..4bca0be95b7a 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -192,26 +192,6 @@ int call_lsm_notifier(enum lsm_event event, void *data); | |||
192 | int register_lsm_notifier(struct notifier_block *nb); | 192 | int register_lsm_notifier(struct notifier_block *nb); |
193 | int unregister_lsm_notifier(struct notifier_block *nb); | 193 | int unregister_lsm_notifier(struct notifier_block *nb); |
194 | 194 | ||
195 | static inline void security_init_mnt_opts(struct security_mnt_opts *opts) | ||
196 | { | ||
197 | opts->mnt_opts = NULL; | ||
198 | opts->mnt_opts_flags = NULL; | ||
199 | opts->num_mnt_opts = 0; | ||
200 | } | ||
201 | |||
202 | static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | ||
203 | { | ||
204 | int i; | ||
205 | if (opts->mnt_opts) | ||
206 | for (i = 0; i < opts->num_mnt_opts; i++) | ||
207 | kfree(opts->mnt_opts[i]); | ||
208 | kfree(opts->mnt_opts); | ||
209 | opts->mnt_opts = NULL; | ||
210 | kfree(opts->mnt_opts_flags); | ||
211 | opts->mnt_opts_flags = NULL; | ||
212 | opts->num_mnt_opts = 0; | ||
213 | } | ||
214 | |||
215 | /* prototypes */ | 195 | /* prototypes */ |
216 | extern int security_init(void); | 196 | extern int security_init(void); |
217 | 197 | ||
@@ -248,8 +228,9 @@ void security_bprm_committing_creds(struct linux_binprm *bprm); | |||
248 | void security_bprm_committed_creds(struct linux_binprm *bprm); | 228 | void security_bprm_committed_creds(struct linux_binprm *bprm); |
249 | int security_sb_alloc(struct super_block *sb); | 229 | int security_sb_alloc(struct super_block *sb); |
250 | void security_sb_free(struct super_block *sb); | 230 | void security_sb_free(struct super_block *sb); |
251 | int security_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts); | 231 | void security_free_mnt_opts(void **mnt_opts); |
252 | int security_sb_remount(struct super_block *sb, struct security_mnt_opts *opts); | 232 | int security_sb_eat_lsm_opts(char *options, void **mnt_opts); |
233 | int security_sb_remount(struct super_block *sb, void *mnt_opts); | ||
253 | int security_sb_kern_mount(struct super_block *sb); | 234 | int security_sb_kern_mount(struct super_block *sb); |
254 | int security_sb_show_options(struct seq_file *m, struct super_block *sb); | 235 | int security_sb_show_options(struct seq_file *m, struct super_block *sb); |
255 | int security_sb_statfs(struct dentry *dentry); | 236 | int security_sb_statfs(struct dentry *dentry); |
@@ -258,14 +239,14 @@ int security_sb_mount(const char *dev_name, const struct path *path, | |||
258 | int security_sb_umount(struct vfsmount *mnt, int flags); | 239 | int security_sb_umount(struct vfsmount *mnt, int flags); |
259 | int security_sb_pivotroot(const struct path *old_path, const struct path *new_path); | 240 | int security_sb_pivotroot(const struct path *old_path, const struct path *new_path); |
260 | int security_sb_set_mnt_opts(struct super_block *sb, | 241 | int security_sb_set_mnt_opts(struct super_block *sb, |
261 | struct security_mnt_opts *opts, | 242 | void *mnt_opts, |
262 | unsigned long kern_flags, | 243 | unsigned long kern_flags, |
263 | unsigned long *set_kern_flags); | 244 | unsigned long *set_kern_flags); |
264 | int security_sb_clone_mnt_opts(const struct super_block *oldsb, | 245 | int security_sb_clone_mnt_opts(const struct super_block *oldsb, |
265 | struct super_block *newsb, | 246 | struct super_block *newsb, |
266 | unsigned long kern_flags, | 247 | unsigned long kern_flags, |
267 | unsigned long *set_kern_flags); | 248 | unsigned long *set_kern_flags); |
268 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts); | 249 | int security_sb_parse_opts_str(char *options, void **mnt_opts); |
269 | int security_dentry_init_security(struct dentry *dentry, int mode, | 250 | int security_dentry_init_security(struct dentry *dentry, int mode, |
270 | const struct qstr *name, void **ctx, | 251 | const struct qstr *name, void **ctx, |
271 | u32 *ctxlen); | 252 | u32 *ctxlen); |
@@ -421,11 +402,7 @@ static inline int unregister_lsm_notifier(struct notifier_block *nb) | |||
421 | return 0; | 402 | return 0; |
422 | } | 403 | } |
423 | 404 | ||
424 | static inline void security_init_mnt_opts(struct security_mnt_opts *opts) | 405 | static inline void security_free_mnt_opts(void **mnt_opts) |
425 | { | ||
426 | } | ||
427 | |||
428 | static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | ||
429 | { | 406 | { |
430 | } | 407 | } |
431 | 408 | ||
@@ -556,13 +533,13 @@ static inline void security_sb_free(struct super_block *sb) | |||
556 | { } | 533 | { } |
557 | 534 | ||
558 | static inline int security_sb_eat_lsm_opts(char *options, | 535 | static inline int security_sb_eat_lsm_opts(char *options, |
559 | struct security_mnt_opts *opts) | 536 | void **mnt_opts) |
560 | { | 537 | { |
561 | return 0; | 538 | return 0; |
562 | } | 539 | } |
563 | 540 | ||
564 | static inline int security_sb_remount(struct super_block *sb, | 541 | static inline int security_sb_remount(struct super_block *sb, |
565 | struct security_mnt_opts *opts) | 542 | void *mnt_opts) |
566 | { | 543 | { |
567 | return 0; | 544 | return 0; |
568 | } | 545 | } |
@@ -602,7 +579,7 @@ static inline int security_sb_pivotroot(const struct path *old_path, | |||
602 | } | 579 | } |
603 | 580 | ||
604 | static inline int security_sb_set_mnt_opts(struct super_block *sb, | 581 | static inline int security_sb_set_mnt_opts(struct super_block *sb, |
605 | struct security_mnt_opts *opts, | 582 | void *mnt_opts, |
606 | unsigned long kern_flags, | 583 | unsigned long kern_flags, |
607 | unsigned long *set_kern_flags) | 584 | unsigned long *set_kern_flags) |
608 | { | 585 | { |
@@ -617,7 +594,7 @@ static inline int security_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
617 | return 0; | 594 | return 0; |
618 | } | 595 | } |
619 | 596 | ||
620 | static inline int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) | 597 | static inline int security_sb_parse_opts_str(char *options, void **mnt_opts) |
621 | { | 598 | { |
622 | return 0; | 599 | return 0; |
623 | } | 600 | } |
diff --git a/security/security.c b/security/security.c index feb18c925349..b7a5a0051807 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -384,16 +384,25 @@ void security_sb_free(struct super_block *sb) | |||
384 | call_void_hook(sb_free_security, sb); | 384 | call_void_hook(sb_free_security, sb); |
385 | } | 385 | } |
386 | 386 | ||
387 | int security_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) | 387 | void security_free_mnt_opts(void **mnt_opts) |
388 | { | 388 | { |
389 | return call_int_hook(sb_eat_lsm_opts, 0, options, opts); | 389 | if (!*mnt_opts) |
390 | return; | ||
391 | call_void_hook(sb_free_mnt_opts, *mnt_opts); | ||
392 | *mnt_opts = NULL; | ||
393 | } | ||
394 | EXPORT_SYMBOL(security_free_mnt_opts); | ||
395 | |||
396 | int security_sb_eat_lsm_opts(char *options, void **mnt_opts) | ||
397 | { | ||
398 | return call_int_hook(sb_eat_lsm_opts, 0, options, mnt_opts); | ||
390 | } | 399 | } |
391 | EXPORT_SYMBOL(security_sb_eat_lsm_opts); | 400 | EXPORT_SYMBOL(security_sb_eat_lsm_opts); |
392 | 401 | ||
393 | int security_sb_remount(struct super_block *sb, | 402 | int security_sb_remount(struct super_block *sb, |
394 | struct security_mnt_opts *opts) | 403 | void *mnt_opts) |
395 | { | 404 | { |
396 | return call_int_hook(sb_remount, 0, sb, opts); | 405 | return call_int_hook(sb_remount, 0, sb, mnt_opts); |
397 | } | 406 | } |
398 | EXPORT_SYMBOL(security_sb_remount); | 407 | EXPORT_SYMBOL(security_sb_remount); |
399 | 408 | ||
@@ -429,13 +438,13 @@ int security_sb_pivotroot(const struct path *old_path, const struct path *new_pa | |||
429 | } | 438 | } |
430 | 439 | ||
431 | int security_sb_set_mnt_opts(struct super_block *sb, | 440 | int security_sb_set_mnt_opts(struct super_block *sb, |
432 | struct security_mnt_opts *opts, | 441 | void *mnt_opts, |
433 | unsigned long kern_flags, | 442 | unsigned long kern_flags, |
434 | unsigned long *set_kern_flags) | 443 | unsigned long *set_kern_flags) |
435 | { | 444 | { |
436 | return call_int_hook(sb_set_mnt_opts, | 445 | return call_int_hook(sb_set_mnt_opts, |
437 | opts->num_mnt_opts ? -EOPNOTSUPP : 0, sb, | 446 | mnt_opts ? -EOPNOTSUPP : 0, sb, |
438 | opts, kern_flags, set_kern_flags); | 447 | mnt_opts, kern_flags, set_kern_flags); |
439 | } | 448 | } |
440 | EXPORT_SYMBOL(security_sb_set_mnt_opts); | 449 | EXPORT_SYMBOL(security_sb_set_mnt_opts); |
441 | 450 | ||
@@ -449,9 +458,9 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb, | |||
449 | } | 458 | } |
450 | EXPORT_SYMBOL(security_sb_clone_mnt_opts); | 459 | EXPORT_SYMBOL(security_sb_clone_mnt_opts); |
451 | 460 | ||
452 | int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts) | 461 | int security_sb_parse_opts_str(char *options, void **mnt_opts) |
453 | { | 462 | { |
454 | return call_int_hook(sb_parse_opts_str, 0, options, opts); | 463 | return call_int_hook(sb_parse_opts_str, 0, options, mnt_opts); |
455 | } | 464 | } |
456 | EXPORT_SYMBOL(security_sb_parse_opts_str); | 465 | EXPORT_SYMBOL(security_sb_parse_opts_str); |
457 | 466 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 11cf2feb27b3..caf7ca7abfc1 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -433,6 +433,19 @@ static void superblock_free_security(struct super_block *sb) | |||
433 | kfree(sbsec); | 433 | kfree(sbsec); |
434 | } | 434 | } |
435 | 435 | ||
436 | static void selinux_free_mnt_opts(void *mnt_opts) | ||
437 | { | ||
438 | struct security_mnt_opts *opts = mnt_opts; | ||
439 | int i; | ||
440 | |||
441 | if (opts->mnt_opts) | ||
442 | for (i = 0; i < opts->num_mnt_opts; i++) | ||
443 | kfree(opts->mnt_opts[i]); | ||
444 | kfree(opts->mnt_opts); | ||
445 | kfree(opts->mnt_opts_flags); | ||
446 | kfree(opts); | ||
447 | } | ||
448 | |||
436 | static inline int inode_doinit(struct inode *inode) | 449 | static inline int inode_doinit(struct inode *inode) |
437 | { | 450 | { |
438 | return inode_doinit_with_dentry(inode, NULL); | 451 | return inode_doinit_with_dentry(inode, NULL); |
@@ -616,7 +629,7 @@ static int bad_option(struct superblock_security_struct *sbsec, char flag, | |||
616 | * labeling information. | 629 | * labeling information. |
617 | */ | 630 | */ |
618 | static int selinux_set_mnt_opts(struct super_block *sb, | 631 | static int selinux_set_mnt_opts(struct super_block *sb, |
619 | struct security_mnt_opts *opts, | 632 | void *mnt_opts, |
620 | unsigned long kern_flags, | 633 | unsigned long kern_flags, |
621 | unsigned long *set_kern_flags) | 634 | unsigned long *set_kern_flags) |
622 | { | 635 | { |
@@ -628,9 +641,10 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
628 | struct inode_security_struct *root_isec; | 641 | struct inode_security_struct *root_isec; |
629 | u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; | 642 | u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; |
630 | u32 defcontext_sid = 0; | 643 | u32 defcontext_sid = 0; |
631 | char **mount_options = opts->mnt_opts; | 644 | struct security_mnt_opts *opts = mnt_opts; |
632 | int *flags = opts->mnt_opts_flags; | 645 | char **mount_options = opts ? opts->mnt_opts : NULL; |
633 | int num_opts = opts->num_mnt_opts; | 646 | int *flags = opts ? opts->mnt_opts_flags : NULL; |
647 | int num_opts = opts ? opts->num_mnt_opts : 0; | ||
634 | 648 | ||
635 | mutex_lock(&sbsec->lock); | 649 | mutex_lock(&sbsec->lock); |
636 | 650 | ||
@@ -982,12 +996,20 @@ out: | |||
982 | } | 996 | } |
983 | 997 | ||
984 | static int selinux_parse_opts_str(char *options, | 998 | static int selinux_parse_opts_str(char *options, |
985 | struct security_mnt_opts *opts) | 999 | void **mnt_opts) |
986 | { | 1000 | { |
987 | char *p; | 1001 | char *p; |
988 | char *context = NULL, *defcontext = NULL; | 1002 | char *context = NULL, *defcontext = NULL; |
989 | char *fscontext = NULL, *rootcontext = NULL; | 1003 | char *fscontext = NULL, *rootcontext = NULL; |
990 | int rc, num_mnt_opts = 0; | 1004 | int rc, num_mnt_opts = 0; |
1005 | struct security_mnt_opts *opts = *mnt_opts; | ||
1006 | |||
1007 | if (!opts) { | ||
1008 | opts = kzalloc(sizeof(struct security_mnt_opts), GFP_KERNEL); | ||
1009 | *mnt_opts = opts; | ||
1010 | if (!opts) | ||
1011 | return -ENOMEM; | ||
1012 | } | ||
991 | 1013 | ||
992 | opts->num_mnt_opts = 0; | 1014 | opts->num_mnt_opts = 0; |
993 | 1015 | ||
@@ -1094,7 +1116,7 @@ static int selinux_parse_opts_str(char *options, | |||
1094 | return 0; | 1116 | return 0; |
1095 | 1117 | ||
1096 | out_err: | 1118 | out_err: |
1097 | security_free_mnt_opts(opts); | 1119 | security_free_mnt_opts(mnt_opts); |
1098 | kfree(context); | 1120 | kfree(context); |
1099 | kfree(defcontext); | 1121 | kfree(defcontext); |
1100 | kfree(fscontext); | 1122 | kfree(fscontext); |
@@ -2714,7 +2736,7 @@ out: | |||
2714 | return rc; | 2736 | return rc; |
2715 | } | 2737 | } |
2716 | 2738 | ||
2717 | static int selinux_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) | 2739 | static int selinux_sb_eat_lsm_opts(char *options, void **mnt_opts) |
2718 | { | 2740 | { |
2719 | char *s = (char *)get_zeroed_page(GFP_KERNEL); | 2741 | char *s = (char *)get_zeroed_page(GFP_KERNEL); |
2720 | int err; | 2742 | int err; |
@@ -2723,14 +2745,14 @@ static int selinux_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts | |||
2723 | return -ENOMEM; | 2745 | return -ENOMEM; |
2724 | err = selinux_sb_copy_data(options, s); | 2746 | err = selinux_sb_copy_data(options, s); |
2725 | if (!err) | 2747 | if (!err) |
2726 | err = selinux_parse_opts_str(s, opts); | 2748 | err = selinux_parse_opts_str(s, mnt_opts); |
2727 | free_page((unsigned long)s); | 2749 | free_page((unsigned long)s); |
2728 | return err; | 2750 | return err; |
2729 | } | 2751 | } |
2730 | 2752 | ||
2731 | static int selinux_sb_remount(struct super_block *sb, | 2753 | static int selinux_sb_remount(struct super_block *sb, void *mnt_opts) |
2732 | struct security_mnt_opts *opts) | ||
2733 | { | 2754 | { |
2755 | struct security_mnt_opts *opts = mnt_opts; | ||
2734 | int i, *flags; | 2756 | int i, *flags; |
2735 | char **mount_options; | 2757 | char **mount_options; |
2736 | struct superblock_security_struct *sbsec = sb->s_security; | 2758 | struct superblock_security_struct *sbsec = sb->s_security; |
@@ -2738,6 +2760,9 @@ static int selinux_sb_remount(struct super_block *sb, | |||
2738 | if (!(sbsec->flags & SE_SBINITIALIZED)) | 2760 | if (!(sbsec->flags & SE_SBINITIALIZED)) |
2739 | return 0; | 2761 | return 0; |
2740 | 2762 | ||
2763 | if (!opts) | ||
2764 | return 0; | ||
2765 | |||
2741 | mount_options = opts->mnt_opts; | 2766 | mount_options = opts->mnt_opts; |
2742 | flags = opts->mnt_opts_flags; | 2767 | flags = opts->mnt_opts_flags; |
2743 | 2768 | ||
@@ -6782,6 +6807,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = { | |||
6782 | LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security), | 6807 | LSM_HOOK_INIT(sb_alloc_security, selinux_sb_alloc_security), |
6783 | LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security), | 6808 | LSM_HOOK_INIT(sb_free_security, selinux_sb_free_security), |
6784 | LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts), | 6809 | LSM_HOOK_INIT(sb_eat_lsm_opts, selinux_sb_eat_lsm_opts), |
6810 | LSM_HOOK_INIT(sb_free_mnt_opts, selinux_free_mnt_opts), | ||
6785 | LSM_HOOK_INIT(sb_remount, selinux_sb_remount), | 6811 | LSM_HOOK_INIT(sb_remount, selinux_sb_remount), |
6786 | LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount), | 6812 | LSM_HOOK_INIT(sb_kern_mount, selinux_sb_kern_mount), |
6787 | LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options), | 6813 | LSM_HOOK_INIT(sb_show_options, selinux_sb_show_options), |
@@ -7051,11 +7077,7 @@ static __init int selinux_init(void) | |||
7051 | 7077 | ||
7052 | static void delayed_superblock_init(struct super_block *sb, void *unused) | 7078 | static void delayed_superblock_init(struct super_block *sb, void *unused) |
7053 | { | 7079 | { |
7054 | struct security_mnt_opts opts; | 7080 | selinux_set_mnt_opts(sb, NULL, 0, NULL); |
7055 | |||
7056 | security_init_mnt_opts(&opts); | ||
7057 | selinux_set_mnt_opts(sb, &opts, 0, NULL); | ||
7058 | security_free_mnt_opts(&opts); | ||
7059 | } | 7081 | } |
7060 | 7082 | ||
7061 | void selinux_complete_init(void) | 7083 | void selinux_complete_init(void) |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 835cca277c2a..81a8112975d4 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -567,6 +567,19 @@ static void smack_sb_free_security(struct super_block *sb) | |||
567 | sb->s_security = NULL; | 567 | sb->s_security = NULL; |
568 | } | 568 | } |
569 | 569 | ||
570 | static void smack_free_mnt_opts(void *mnt_opts) | ||
571 | { | ||
572 | struct security_mnt_opts *opts = mnt_opts; | ||
573 | int i; | ||
574 | |||
575 | if (opts->mnt_opts) | ||
576 | for (i = 0; i < opts->num_mnt_opts; i++) | ||
577 | kfree(opts->mnt_opts[i]); | ||
578 | kfree(opts->mnt_opts); | ||
579 | kfree(opts->mnt_opts_flags); | ||
580 | kfree(opts); | ||
581 | } | ||
582 | |||
570 | /** | 583 | /** |
571 | * smack_sb_copy_data - copy mount options data for processing | 584 | * smack_sb_copy_data - copy mount options data for processing |
572 | * @orig: where to start | 585 | * @orig: where to start |
@@ -624,8 +637,9 @@ static int smack_sb_copy_data(char *orig, char *smackopts) | |||
624 | * converts Smack specific mount options to generic security option format | 637 | * converts Smack specific mount options to generic security option format |
625 | */ | 638 | */ |
626 | static int smack_parse_opts_str(char *options, | 639 | static int smack_parse_opts_str(char *options, |
627 | struct security_mnt_opts *opts) | 640 | void **mnt_opts) |
628 | { | 641 | { |
642 | struct security_mnt_opts *opts = *mnt_opts; | ||
629 | char *p; | 643 | char *p; |
630 | char *fsdefault = NULL; | 644 | char *fsdefault = NULL; |
631 | char *fsfloor = NULL; | 645 | char *fsfloor = NULL; |
@@ -636,11 +650,17 @@ static int smack_parse_opts_str(char *options, | |||
636 | int num_mnt_opts = 0; | 650 | int num_mnt_opts = 0; |
637 | int token; | 651 | int token; |
638 | 652 | ||
639 | opts->num_mnt_opts = 0; | ||
640 | |||
641 | if (!options) | 653 | if (!options) |
642 | return 0; | 654 | return 0; |
643 | 655 | ||
656 | if (!opts) { | ||
657 | opts = kzalloc(sizeof(struct security_mnt_opts), GFP_KERNEL); | ||
658 | *mnt_opts = opts; | ||
659 | if (!opts) | ||
660 | return -ENOMEM; | ||
661 | } | ||
662 | opts->num_mnt_opts = 0; | ||
663 | |||
644 | while ((p = strsep(&options, ",")) != NULL) { | 664 | while ((p = strsep(&options, ",")) != NULL) { |
645 | substring_t args[MAX_OPT_ARGS]; | 665 | substring_t args[MAX_OPT_ARGS]; |
646 | 666 | ||
@@ -735,11 +755,11 @@ out_err: | |||
735 | kfree(fshat); | 755 | kfree(fshat); |
736 | kfree(fsroot); | 756 | kfree(fsroot); |
737 | kfree(fstransmute); | 757 | kfree(fstransmute); |
738 | security_free_mnt_opts(opts); | 758 | security_free_mnt_opts(mnt_opts); |
739 | return rc; | 759 | return rc; |
740 | } | 760 | } |
741 | 761 | ||
742 | static int smack_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) | 762 | static int smack_sb_eat_lsm_opts(char *options, void **mnt_opts) |
743 | { | 763 | { |
744 | char *s = (char *)get_zeroed_page(GFP_KERNEL); | 764 | char *s = (char *)get_zeroed_page(GFP_KERNEL); |
745 | int err; | 765 | int err; |
@@ -748,7 +768,7 @@ static int smack_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) | |||
748 | return -ENOMEM; | 768 | return -ENOMEM; |
749 | err = smack_sb_copy_data(options, s); | 769 | err = smack_sb_copy_data(options, s); |
750 | if (!err) | 770 | if (!err) |
751 | err = smack_parse_opts_str(s, opts); | 771 | err = smack_parse_opts_str(s, mnt_opts); |
752 | free_page((unsigned long)s); | 772 | free_page((unsigned long)s); |
753 | return err; | 773 | return err; |
754 | } | 774 | } |
@@ -766,7 +786,7 @@ static int smack_sb_eat_lsm_opts(char *options, struct security_mnt_opts *opts) | |||
766 | * labels. | 786 | * labels. |
767 | */ | 787 | */ |
768 | static int smack_set_mnt_opts(struct super_block *sb, | 788 | static int smack_set_mnt_opts(struct super_block *sb, |
769 | struct security_mnt_opts *opts, | 789 | void *mnt_opts, |
770 | unsigned long kern_flags, | 790 | unsigned long kern_flags, |
771 | unsigned long *set_kern_flags) | 791 | unsigned long *set_kern_flags) |
772 | { | 792 | { |
@@ -776,7 +796,8 @@ static int smack_set_mnt_opts(struct super_block *sb, | |||
776 | struct inode_smack *isp; | 796 | struct inode_smack *isp; |
777 | struct smack_known *skp; | 797 | struct smack_known *skp; |
778 | int i; | 798 | int i; |
779 | int num_opts = opts->num_mnt_opts; | 799 | struct security_mnt_opts *opts = mnt_opts; |
800 | int num_opts = opts ? opts->num_mnt_opts : 0; | ||
780 | int transmute = 0; | 801 | int transmute = 0; |
781 | 802 | ||
782 | if (sp->smk_flags & SMK_SB_INITIALIZED) | 803 | if (sp->smk_flags & SMK_SB_INITIALIZED) |
@@ -4651,6 +4672,7 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { | |||
4651 | 4672 | ||
4652 | LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security), | 4673 | LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security), |
4653 | LSM_HOOK_INIT(sb_free_security, smack_sb_free_security), | 4674 | LSM_HOOK_INIT(sb_free_security, smack_sb_free_security), |
4675 | LSM_HOOK_INIT(sb_free_mnt_opts, smack_free_mnt_opts), | ||
4654 | LSM_HOOK_INIT(sb_eat_lsm_opts, smack_sb_eat_lsm_opts), | 4676 | LSM_HOOK_INIT(sb_eat_lsm_opts, smack_sb_eat_lsm_opts), |
4655 | LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), | 4677 | LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), |
4656 | LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts), | 4678 | LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts), |