diff options
Diffstat (limited to 'security/smack/smack_lsm.c')
| -rw-r--r-- | security/smack/smack_lsm.c | 145 |
1 files changed, 69 insertions, 76 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index b0be893ad44d..14f52be78c75 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -219,8 +219,6 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
| 219 | * smack_syslog - Smack approval on syslog | 219 | * smack_syslog - Smack approval on syslog |
| 220 | * @type: message type | 220 | * @type: message type |
| 221 | * | 221 | * |
| 222 | * Require that the task has the floor label | ||
| 223 | * | ||
| 224 | * Returns 0 on success, error code otherwise. | 222 | * Returns 0 on success, error code otherwise. |
| 225 | */ | 223 | */ |
| 226 | static int smack_syslog(int typefrom_file) | 224 | static int smack_syslog(int typefrom_file) |
| @@ -231,7 +229,7 @@ static int smack_syslog(int typefrom_file) | |||
| 231 | if (smack_privileged(CAP_MAC_OVERRIDE)) | 229 | if (smack_privileged(CAP_MAC_OVERRIDE)) |
| 232 | return 0; | 230 | return 0; |
| 233 | 231 | ||
| 234 | if (skp != &smack_known_floor) | 232 | if (smack_syslog_label != NULL && smack_syslog_label != skp) |
| 235 | rc = -EACCES; | 233 | rc = -EACCES; |
| 236 | 234 | ||
| 237 | return rc; | 235 | return rc; |
| @@ -341,10 +339,12 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
| 341 | struct inode *inode = root->d_inode; | 339 | struct inode *inode = root->d_inode; |
| 342 | struct superblock_smack *sp = sb->s_security; | 340 | struct superblock_smack *sp = sb->s_security; |
| 343 | struct inode_smack *isp; | 341 | struct inode_smack *isp; |
| 342 | struct smack_known *skp; | ||
| 344 | char *op; | 343 | char *op; |
| 345 | char *commap; | 344 | char *commap; |
| 346 | char *nsp; | 345 | char *nsp; |
| 347 | int transmute = 0; | 346 | int transmute = 0; |
| 347 | int specified = 0; | ||
| 348 | 348 | ||
| 349 | if (sp->smk_initialized) | 349 | if (sp->smk_initialized) |
| 350 | return 0; | 350 | return 0; |
| @@ -359,34 +359,56 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
| 359 | if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { | 359 | if (strncmp(op, SMK_FSHAT, strlen(SMK_FSHAT)) == 0) { |
| 360 | op += strlen(SMK_FSHAT); | 360 | op += strlen(SMK_FSHAT); |
| 361 | nsp = smk_import(op, 0); | 361 | nsp = smk_import(op, 0); |
| 362 | if (nsp != NULL) | 362 | if (nsp != NULL) { |
| 363 | sp->smk_hat = nsp; | 363 | sp->smk_hat = nsp; |
| 364 | specified = 1; | ||
| 365 | } | ||
| 364 | } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { | 366 | } else if (strncmp(op, SMK_FSFLOOR, strlen(SMK_FSFLOOR)) == 0) { |
| 365 | op += strlen(SMK_FSFLOOR); | 367 | op += strlen(SMK_FSFLOOR); |
| 366 | nsp = smk_import(op, 0); | 368 | nsp = smk_import(op, 0); |
| 367 | if (nsp != NULL) | 369 | if (nsp != NULL) { |
| 368 | sp->smk_floor = nsp; | 370 | sp->smk_floor = nsp; |
| 371 | specified = 1; | ||
| 372 | } | ||
| 369 | } else if (strncmp(op, SMK_FSDEFAULT, | 373 | } else if (strncmp(op, SMK_FSDEFAULT, |
| 370 | strlen(SMK_FSDEFAULT)) == 0) { | 374 | strlen(SMK_FSDEFAULT)) == 0) { |
| 371 | op += strlen(SMK_FSDEFAULT); | 375 | op += strlen(SMK_FSDEFAULT); |
| 372 | nsp = smk_import(op, 0); | 376 | nsp = smk_import(op, 0); |
| 373 | if (nsp != NULL) | 377 | if (nsp != NULL) { |
| 374 | sp->smk_default = nsp; | 378 | sp->smk_default = nsp; |
| 379 | specified = 1; | ||
| 380 | } | ||
| 375 | } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { | 381 | } else if (strncmp(op, SMK_FSROOT, strlen(SMK_FSROOT)) == 0) { |
| 376 | op += strlen(SMK_FSROOT); | 382 | op += strlen(SMK_FSROOT); |
| 377 | nsp = smk_import(op, 0); | 383 | nsp = smk_import(op, 0); |
| 378 | if (nsp != NULL) | 384 | if (nsp != NULL) { |
| 379 | sp->smk_root = nsp; | 385 | sp->smk_root = nsp; |
| 386 | specified = 1; | ||
| 387 | } | ||
| 380 | } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { | 388 | } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { |
| 381 | op += strlen(SMK_FSTRANS); | 389 | op += strlen(SMK_FSTRANS); |
| 382 | nsp = smk_import(op, 0); | 390 | nsp = smk_import(op, 0); |
| 383 | if (nsp != NULL) { | 391 | if (nsp != NULL) { |
| 384 | sp->smk_root = nsp; | 392 | sp->smk_root = nsp; |
| 385 | transmute = 1; | 393 | transmute = 1; |
| 394 | specified = 1; | ||
| 386 | } | 395 | } |
| 387 | } | 396 | } |
| 388 | } | 397 | } |
| 389 | 398 | ||
| 399 | if (!smack_privileged(CAP_MAC_ADMIN)) { | ||
| 400 | /* | ||
| 401 | * Unprivileged mounts don't get to specify Smack values. | ||
| 402 | */ | ||
| 403 | if (specified) | ||
| 404 | return -EPERM; | ||
| 405 | /* | ||
| 406 | * Unprivileged mounts get root and default from the caller. | ||
| 407 | */ | ||
| 408 | skp = smk_of_current(); | ||
| 409 | sp->smk_root = skp->smk_known; | ||
| 410 | sp->smk_default = skp->smk_known; | ||
| 411 | } | ||
| 390 | /* | 412 | /* |
| 391 | * Initialize the root inode. | 413 | * Initialize the root inode. |
| 392 | */ | 414 | */ |
| @@ -423,53 +445,6 @@ static int smack_sb_statfs(struct dentry *dentry) | |||
| 423 | return rc; | 445 | return rc; |
| 424 | } | 446 | } |
| 425 | 447 | ||
| 426 | /** | ||
| 427 | * smack_sb_mount - Smack check for mounting | ||
| 428 | * @dev_name: unused | ||
| 429 | * @path: mount point | ||
| 430 | * @type: unused | ||
| 431 | * @flags: unused | ||
| 432 | * @data: unused | ||
| 433 | * | ||
| 434 | * Returns 0 if current can write the floor of the filesystem | ||
| 435 | * being mounted on, an error code otherwise. | ||
| 436 | */ | ||
| 437 | static int smack_sb_mount(const char *dev_name, struct path *path, | ||
| 438 | const char *type, unsigned long flags, void *data) | ||
| 439 | { | ||
| 440 | struct superblock_smack *sbp = path->dentry->d_sb->s_security; | ||
| 441 | struct smk_audit_info ad; | ||
| 442 | |||
| 443 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | ||
| 444 | smk_ad_setfield_u_fs_path(&ad, *path); | ||
| 445 | |||
| 446 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); | ||
| 447 | } | ||
| 448 | |||
| 449 | /** | ||
| 450 | * smack_sb_umount - Smack check for unmounting | ||
| 451 | * @mnt: file system to unmount | ||
| 452 | * @flags: unused | ||
| 453 | * | ||
| 454 | * Returns 0 if current can write the floor of the filesystem | ||
| 455 | * being unmounted, an error code otherwise. | ||
| 456 | */ | ||
| 457 | static int smack_sb_umount(struct vfsmount *mnt, int flags) | ||
| 458 | { | ||
| 459 | struct superblock_smack *sbp; | ||
| 460 | struct smk_audit_info ad; | ||
| 461 | struct path path; | ||
| 462 | |||
| 463 | path.dentry = mnt->mnt_root; | ||
| 464 | path.mnt = mnt; | ||
| 465 | |||
| 466 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | ||
| 467 | smk_ad_setfield_u_fs_path(&ad, path); | ||
| 468 | |||
| 469 | sbp = path.dentry->d_sb->s_security; | ||
| 470 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); | ||
| 471 | } | ||
| 472 | |||
| 473 | /* | 448 | /* |
| 474 | * BPRM hooks | 449 | * BPRM hooks |
| 475 | */ | 450 | */ |
| @@ -837,31 +812,43 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
| 837 | const void *value, size_t size, int flags) | 812 | const void *value, size_t size, int flags) |
| 838 | { | 813 | { |
| 839 | struct smk_audit_info ad; | 814 | struct smk_audit_info ad; |
| 815 | struct smack_known *skp; | ||
| 816 | int check_priv = 0; | ||
| 817 | int check_import = 0; | ||
| 818 | int check_star = 0; | ||
| 840 | int rc = 0; | 819 | int rc = 0; |
| 841 | 820 | ||
| 821 | /* | ||
| 822 | * Check label validity here so import won't fail in post_setxattr | ||
| 823 | */ | ||
| 842 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || | 824 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
| 843 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 825 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
| 844 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || | 826 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) { |
| 845 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || | 827 | check_priv = 1; |
| 846 | strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { | 828 | check_import = 1; |
| 847 | if (!smack_privileged(CAP_MAC_ADMIN)) | 829 | } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || |
| 848 | rc = -EPERM; | 830 | strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { |
| 849 | /* | 831 | check_priv = 1; |
| 850 | * check label validity here so import wont fail on | 832 | check_import = 1; |
| 851 | * post_setxattr | 833 | check_star = 1; |
| 852 | */ | ||
| 853 | if (size == 0 || size >= SMK_LONGLABEL || | ||
| 854 | smk_import(value, size) == NULL) | ||
| 855 | rc = -EINVAL; | ||
| 856 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { | 834 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { |
| 857 | if (!smack_privileged(CAP_MAC_ADMIN)) | 835 | check_priv = 1; |
| 858 | rc = -EPERM; | ||
| 859 | if (size != TRANS_TRUE_SIZE || | 836 | if (size != TRANS_TRUE_SIZE || |
| 860 | strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) | 837 | strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) |
| 861 | rc = -EINVAL; | 838 | rc = -EINVAL; |
| 862 | } else | 839 | } else |
| 863 | rc = cap_inode_setxattr(dentry, name, value, size, flags); | 840 | rc = cap_inode_setxattr(dentry, name, value, size, flags); |
| 864 | 841 | ||
| 842 | if (check_priv && !smack_privileged(CAP_MAC_ADMIN)) | ||
| 843 | rc = -EPERM; | ||
| 844 | |||
| 845 | if (rc == 0 && check_import) { | ||
| 846 | skp = smk_import_entry(value, size); | ||
| 847 | if (skp == NULL || (check_star && | ||
| 848 | (skp == &smack_known_star || skp == &smack_known_web))) | ||
| 849 | rc = -EINVAL; | ||
| 850 | } | ||
| 851 | |||
| 865 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); | 852 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
| 866 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 853 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
| 867 | 854 | ||
| @@ -1364,7 +1351,7 @@ static int smack_file_receive(struct file *file) | |||
| 1364 | int may = 0; | 1351 | int may = 0; |
| 1365 | struct smk_audit_info ad; | 1352 | struct smk_audit_info ad; |
| 1366 | 1353 | ||
| 1367 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1354 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
| 1368 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | 1355 | smk_ad_setfield_u_fs_path(&ad, file->f_path); |
| 1369 | /* | 1356 | /* |
| 1370 | * This code relies on bitmasks. | 1357 | * This code relies on bitmasks. |
| @@ -2847,8 +2834,17 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 2847 | if (rc >= 0) | 2834 | if (rc >= 0) |
| 2848 | transflag = SMK_INODE_TRANSMUTE; | 2835 | transflag = SMK_INODE_TRANSMUTE; |
| 2849 | } | 2836 | } |
| 2850 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); | 2837 | /* |
| 2851 | isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); | 2838 | * Don't let the exec or mmap label be "*" or "@". |
| 2839 | */ | ||
| 2840 | skp = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); | ||
| 2841 | if (skp == &smack_known_star || skp == &smack_known_web) | ||
| 2842 | skp = NULL; | ||
| 2843 | isp->smk_task = skp; | ||
| 2844 | skp = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); | ||
| 2845 | if (skp == &smack_known_star || skp == &smack_known_web) | ||
| 2846 | skp = NULL; | ||
| 2847 | isp->smk_mmap = skp; | ||
| 2852 | 2848 | ||
| 2853 | dput(dp); | 2849 | dput(dp); |
| 2854 | break; | 2850 | break; |
| @@ -3620,9 +3616,8 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, | |||
| 3620 | struct smack_known *skp; | 3616 | struct smack_known *skp; |
| 3621 | char *rule = vrule; | 3617 | char *rule = vrule; |
| 3622 | 3618 | ||
| 3623 | if (!rule) { | 3619 | if (unlikely(!rule)) { |
| 3624 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 3620 | WARN_ONCE(1, "Smack: missing rule\n"); |
| 3625 | "Smack: missing rule\n"); | ||
| 3626 | return -ENOENT; | 3621 | return -ENOENT; |
| 3627 | } | 3622 | } |
| 3628 | 3623 | ||
| @@ -3743,8 +3738,6 @@ struct security_operations smack_ops = { | |||
| 3743 | .sb_copy_data = smack_sb_copy_data, | 3738 | .sb_copy_data = smack_sb_copy_data, |
| 3744 | .sb_kern_mount = smack_sb_kern_mount, | 3739 | .sb_kern_mount = smack_sb_kern_mount, |
| 3745 | .sb_statfs = smack_sb_statfs, | 3740 | .sb_statfs = smack_sb_statfs, |
| 3746 | .sb_mount = smack_sb_mount, | ||
| 3747 | .sb_umount = smack_sb_umount, | ||
| 3748 | 3741 | ||
| 3749 | .bprm_set_creds = smack_bprm_set_creds, | 3742 | .bprm_set_creds = smack_bprm_set_creds, |
| 3750 | .bprm_committing_creds = smack_bprm_committing_creds, | 3743 | .bprm_committing_creds = smack_bprm_committing_creds, |
