Smack Bring-up mode including unconfined feature
authorjooseong.lee <jooseong.lee@samsung.com>
Wed, 25 Mar 2015 02:05:50 +0000 (11:05 +0900)
committerSooyoung Ha <yoosah.ha@samsung.com>
Wed, 25 Mar 2015 05:32:44 +0000 (14:32 +0900)
Change-Id: Ie875af7fcde4af981aab4eb0219eb7ece74ff558
Signed-off-by: jooseong.lee <jooseong.lee@samsung.com>
arch/x86/configs/i386_tizen_emul_defconfig
security/smack/Kconfig
security/smack/smack.h
security/smack/smack_access.c
security/smack/smack_lsm.c
security/smack/smackfs.c

index adba740..2cfcb6e 100644 (file)
@@ -3627,6 +3627,7 @@ CONFIG_SECURITY_NETWORK=y
 # CONFIG_SECURITY_PATH is not set
 # CONFIG_SECURITY_SELINUX is not set
 CONFIG_SECURITY_SMACK=y
+CONFIG_SECURITY_SMACK_BRINGUP=y
 # CONFIG_SECURITY_TOMOYO is not set
 # CONFIG_SECURITY_APPARMOR is not set
 # CONFIG_SECURITY_YAMA is not set
index e69de9c..ba5527e 100644 (file)
@@ -12,3 +12,19 @@ config SECURITY_SMACK
          of other mandatory security schemes.
          If you are unsure how to answer this question, answer N.
 
+config SECURITY_SMACK_BRINGUP
+        bool "Reporting on access granted by Smack rules"
+        depends on SECURITY_SMACK
+        default n
+        help
+          Enable the bring-up ("b") access mode in Smack rules.
+          When access is granted by a rule with the "b" mode a
+          message about the access requested is generated. The
+          intention is that a process can be granted a wide set
+          of access initially with the bringup mode set on the
+          rules. The developer can use the information to
+          identify which rules are necessary and what accesses
+          may be inappropriate. The developer can reduce the
+          access rule set once the behavior is well understood.
+          This is a superior mechanism to the oft abused
+          "permissive" mode of other systems.
index 7b912f5..f4af1b1 100644 (file)
@@ -105,6 +105,7 @@ struct task_smack {
 #define        SMK_INODE_INSTANT       0x01    /* inode is instantiated */
 #define        SMK_INODE_TRANSMUTE     0x02    /* directory is transmuting */
 #define        SMK_INODE_CHANGED       0x04    /* smack was transmuted */
+#define SMK_INODE_IMPURE        0x08    /* involved in an impure transaction */
 
 /*
  * A label access rule.
@@ -191,6 +192,11 @@ struct smk_port_label {
  */
 #define MAY_TRANSMUTE  0x00001000      /* Controls directory labeling */
 #define MAY_LOCK       0x00002000      /* Locks should be writes, but ... */
+#define MAY_BRINGUP    0x00004000      /* Report use of this rule */
+
+#define SMACK_BRINGUP_ALLOW            1       /* Allow bringup mode */
+#define SMACK_UNCONFINED_SUBJECT       2       /* Allow unconfined label */
+#define SMACK_UNCONFINED_OBJECT                        3       /* Allow unconfined label */
 
 /*
  * Just to make the common cases easier to deal with
@@ -200,9 +206,9 @@ struct smk_port_label {
 #define MAY_NOT                0
 
 /*
- * Number of access types used by Smack (rwxatl)
+ * Number of access types used by Smack (rwxatlb)
  */
-#define SMK_NUM_ACCESS_TYPE 6
+#define SMK_NUM_ACCESS_TYPE 7
 
 /* SMACK data */
 struct smack_audit_data {
@@ -258,6 +264,9 @@ extern int smack_cipso_mapped;
 extern struct smack_known *smack_net_ambient;
 extern struct smack_known *smack_onlycap;
 extern struct smack_known *smack_syslog_label;
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+extern struct smack_known *smack_unconfined;
+#endif
 extern const char *smack_cipso_option;
 extern int smack_ptrace_rule;
 
index 821f283..a0c834b 100644 (file)
@@ -130,7 +130,8 @@ int smk_access(struct smack_known *subject_known, char *object_label,
 
        /*
         * Hardcoded comparisons.
-        *
+        */
+       /*
         * A star subject can't access any object.
         */
        if (subject_known == &smack_known_star) {
@@ -179,11 +180,27 @@ int smk_access(struct smack_known *subject_known, char *object_label,
                                &subject_known->smk_rules);
        rcu_read_unlock();
 
-       if (may > 0 && (request & may) == request)
+       if (may <= 0 || (request & may) != request) {
+               rc = -EACCES;
                goto out_audit;
+       }
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+       if (may & MAY_BRINGUP)
+               rc = SMACK_BRINGUP_ALLOW;
+#endif
 
-       rc = -EACCES;
 out_audit:
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+       if (rc < 0) {
+               if (smack_unconfined != NULL) {
+                       if (object_label == smack_unconfined->smk_known)
+                               rc = SMACK_UNCONFINED_OBJECT;
+                       if (subject_known->smk_known == smack_unconfined->smk_known)
+                               rc = SMACK_UNCONFINED_SUBJECT;
+               }
+       }
+#endif
+
 #ifdef CONFIG_AUDIT
        if (a)
                smack_log(subject_known->smk_known, object_label, request,
@@ -215,7 +232,7 @@ int smk_tskacc(struct task_smack *subject, char *obj_label,
         * Check the global rule list
         */
        rc = smk_access(skp, obj_label, mode, NULL);
-       if (rc == 0) {
+       if (rc >= 0) {
                /*
                 * If there is an entry in the task's rule list
                 * it can further restrict access.
@@ -325,12 +342,16 @@ static void smack_log_callback(struct audit_buffer *ab, void *a)
 void smack_log(char *subject_label, char *object_label, int request,
               int result, struct smk_audit_info *ad)
 {
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+       char request_buffer[SMK_NUM_ACCESS_TYPE + 5];
+#else
        char request_buffer[SMK_NUM_ACCESS_TYPE + 1];
+#endif
        struct smack_audit_data *sad;
        struct common_audit_data *a = &ad->a;
 
        /* check if we have to log the current event */
-       if (result != 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
+       if (result < 0 && (log_policy & SMACK_AUDIT_DENIED) == 0)
                return;
        if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0)
                return;
@@ -344,6 +365,22 @@ void smack_log(char *subject_label, char *object_label, int request,
        smack_str_from_perm(request_buffer, request);
        sad->subject = subject_label;
        sad->object  = object_label;
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+       /*
+        * The result may be positive in bringup mode.
+        * A positive result is an allow, but not for normal reasons.
+        * Mark it as successful, but don't filter it out even if
+        * the logging policy says to do so.
+        */
+       if (result == SMACK_UNCONFINED_SUBJECT)
+               strcat(request_buffer, "(US)");
+       else if (result == SMACK_UNCONFINED_OBJECT)
+               strcat(request_buffer, "(UO)");
+
+       if (result > 0)
+               result = 0;
+#endif
+
        sad->request = request_buffer;
        sad->result  = result;
 
index f7d0d43..716ab8e 100644 (file)
 LIST_HEAD(smk_ipv6_port_list);
 static struct kmem_cache *smack_inode_cache;
 
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+static char *smk_bu_mess[] = {
+       "Bringup Error",        /* Unused */
+       "Bringup",              /* SMACK_BRINGUP_ALLOW */
+       "Unconfined Subject",   /* SMACK_UNCONFINED_SUBJECT */
+       "Unconfined Object",    /* SMACK_UNCONFINED_OBJECT */
+};
+
+static void smk_bu_mode(int mode, char *s)
+{
+       int i = 0;
+
+       if (mode & MAY_READ)
+               s[i++] = 'r';
+       if (mode & MAY_WRITE)
+               s[i++] = 'w';
+       if (mode & MAY_EXEC)
+               s[i++] = 'x';
+       if (mode & MAY_APPEND)
+               s[i++] = 'a';
+       if (mode & MAY_TRANSMUTE)
+               s[i++] = 't';
+       if (mode & MAY_LOCK)
+               s[i++] = 'l';
+       if (i == 0)
+               s[i++] = '-';
+       s[i] = '\0';
+}
+#endif
+
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+static int smk_bu_note(char *note, struct smack_known *sskp, char *osp,
+                       int mode, int rc)
+{
+       char acc[SMK_NUM_ACCESS_TYPE + 1];
+
+       if (rc <= 0)
+               return rc;
+       if (rc > SMACK_UNCONFINED_OBJECT)
+               rc = 0;
+
+       smk_bu_mode(mode, acc);
+       printk(KERN_WARNING "Smack %s: (%s %s %s) %s\n", smk_bu_mess[rc],
+               sskp->smk_known, osp, acc, note);
+       return 0;
+}
+#else
+#define smk_bu_note(note, sskp, osp, mode, RC) (RC)
+#endif
+
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+static int smk_bu_current(char *note, char *osp, int mode, int rc)
+{
+       struct task_smack *tsp = current_security();
+       char acc[SMK_NUM_ACCESS_TYPE + 1];
+
+       if (rc <= 0)
+               return rc;
+       if (rc > SMACK_UNCONFINED_OBJECT)
+               rc = 0;
+
+       smk_bu_mode(mode, acc);
+       printk(KERN_WARNING "Smack %s: (%s %s %s) %s %s\n", smk_bu_mess[rc],
+               tsp->smk_task->smk_known, osp, acc, current->comm, note);
+       return 0;
+}
+#else
+#define smk_bu_current(note, osp, mode, RC) (RC)
+#endif
+
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+static int smk_bu_task(struct task_struct *otp, int mode, int rc)
+{
+       struct task_smack *tsp = current_security();
+       struct task_smack *otsp = task_security(otp);
+       char acc[SMK_NUM_ACCESS_TYPE + 1];
+
+       if (rc <= 0)
+               return rc;
+       if (rc > SMACK_UNCONFINED_OBJECT)
+               rc = 0;
+
+       smk_bu_mode(mode, acc);
+       printk(KERN_WARNING "Smack %s: (%s %s %s) %s to %s\n", smk_bu_mess[rc],
+               tsp->smk_task->smk_known, otsp->smk_task->smk_known, acc,
+               current->comm, otp->comm);
+       return 0;
+}
+#else
+#define smk_bu_task(otp, mode, RC) (RC)
+#endif
+
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+static int smk_bu_inode(struct inode *inode, int mode, int rc)
+{
+       struct task_smack *tsp = current_security();
+       struct inode_smack *isp = inode->i_security;
+       char acc[SMK_NUM_ACCESS_TYPE + 1];
+
+       if (isp->smk_flags & SMK_INODE_IMPURE)
+               printk(KERN_WARNING "Smack Unconfined Corruption: inode=(%s %ld) %s\n",
+                       inode->i_sb->s_id, inode->i_ino, current->comm);
+
+       if (rc <= 0)
+               return rc;
+       if (rc > SMACK_UNCONFINED_OBJECT)
+               rc = 0;
+       if (rc == SMACK_UNCONFINED_SUBJECT &&
+           (mode & (MAY_WRITE | MAY_APPEND)))
+               isp->smk_flags |= SMK_INODE_IMPURE;
+
+       smk_bu_mode(mode, acc);
+
+       printk(KERN_WARNING "Smack %s: (%s %s %s) inode=(%s %ld) %s\n", smk_bu_mess[rc],
+               tsp->smk_task->smk_known, isp->smk_inode, acc,
+               inode->i_sb->s_id, inode->i_ino, current->comm);
+       return 0;
+}
+#else
+#define smk_bu_inode(inode, mode, RC) (RC)
+#endif
+
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+static int smk_bu_file(struct file *file, int mode, int rc)
+{
+       struct task_smack *tsp = current_security();
+       struct smack_known *sskp = tsp->smk_task;
+       struct inode *inode = file->f_inode;
+       struct inode_smack *isp = inode->i_security;
+       char acc[SMK_NUM_ACCESS_TYPE + 1];
+
+       if (isp->smk_flags & SMK_INODE_IMPURE)
+               printk(KERN_WARNING "Smack Unconfined Corruption: inode=(%s %ld) %s\n",
+                       inode->i_sb->s_id, inode->i_ino, current->comm);
+
+       if (rc <= 0)
+               return rc;
+       if (rc > SMACK_UNCONFINED_OBJECT)
+               rc = 0;
+
+       smk_bu_mode(mode, acc);
+       printk(KERN_WARNING "Smack %s: (%s %s %s) file=(%s %ld %s) %s\n", smk_bu_mess[rc],
+               sskp->smk_known, (char *)file->f_security, acc,
+               inode->i_sb->s_id, inode->i_ino, file->f_dentry->d_name.name,
+               current->comm);
+       return 0;
+}
+#else
+#define smk_bu_file(file, mode, RC) (RC)
+#endif
+
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+static int smk_bu_credfile(const struct cred *cred, struct file *file,
+                               int mode, int rc)
+{
+       struct task_smack *tsp = cred->security;
+       struct smack_known *sskp = tsp->smk_task;
+       struct inode *inode = file->f_inode;
+       struct inode_smack *isp = inode->i_security;
+       char acc[SMK_NUM_ACCESS_TYPE + 1];
+
+       if (isp->smk_flags & SMK_INODE_IMPURE)
+               printk(KERN_WARNING "Smack Unconfined Corruption: inode=(%s %ld) %s\n",
+                       inode->i_sb->s_id, inode->i_ino, current->comm);
+
+       if (rc <= 0)
+               return rc;
+       if (rc > SMACK_UNCONFINED_OBJECT)
+               rc = 0;
+
+       smk_bu_mode(mode, acc);
+       printk(KERN_WARNING "Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
+               sskp->smk_known, smk_of_inode(inode), acc,
+               inode->i_sb->s_id, inode->i_ino, file->f_dentry->d_name.name,
+               current->comm);
+       return 0;
+}
+#else
+#define smk_bu_credfile(cred, file, mode, RC) (RC)
+#endif
+
 /**
  * smk_fetch - Fetch the smack label from a file.
  * @ip: a pointer to the inode
@@ -508,6 +689,7 @@ static int smack_sb_statfs(struct dentry *dentry)
        smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
        rc = smk_curacc(sbp->smk_floor, MAY_READ, &ad);
+       rc = smk_bu_current("statfs", sbp->smk_floor, MAY_READ, rc);
        return rc;
 }
 
@@ -698,11 +880,13 @@ static int smack_inode_link(struct dentry *old_dentry, struct inode *dir,
 
        isp = smk_of_inode(old_dentry->d_inode);
        rc = smk_curacc(isp, MAY_WRITE, &ad);
+       rc = smk_bu_inode(old_dentry->d_inode, MAY_WRITE, rc);
 
        if (rc == 0 && new_dentry->d_inode != NULL) {
                isp = smk_of_inode(new_dentry->d_inode);
                smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
                rc = smk_curacc(isp, MAY_WRITE, &ad);
+               rc = smk_bu_inode(new_dentry->d_inode, MAY_WRITE, rc);
        }
 
        return rc;
@@ -729,6 +913,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
         * You need write access to the thing you're unlinking
         */
        rc = smk_curacc(smk_of_inode(ip), MAY_WRITE, &ad);
+       rc = smk_bu_inode(ip, MAY_WRITE, rc);
        if (rc == 0) {
                /*
                 * You also need write access to the containing directory
@@ -736,6 +921,7 @@ static int smack_inode_unlink(struct inode *dir, struct dentry *dentry)
                smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE);
                smk_ad_setfield_u_fs_inode(&ad, dir);
                rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
+               rc = smk_bu_inode(dir, MAY_WRITE, rc);
        }
        return rc;
 }
@@ -760,6 +946,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
         * You need write access to the thing you're removing
         */
        rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
+       rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
        if (rc == 0) {
                /*
                 * You also need write access to the containing directory
@@ -767,6 +954,7 @@ static int smack_inode_rmdir(struct inode *dir, struct dentry *dentry)
                smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE);
                smk_ad_setfield_u_fs_inode(&ad, dir);
                rc = smk_curacc(smk_of_inode(dir), MAY_WRITE, &ad);
+               rc = smk_bu_inode(dir, MAY_WRITE, rc);
        }
 
        return rc;
@@ -798,11 +986,13 @@ static int smack_inode_rename(struct inode *old_inode,
 
        isp = smk_of_inode(old_dentry->d_inode);
        rc = smk_curacc(isp, MAY_READWRITE, &ad);
+       rc = smk_bu_inode(old_dentry->d_inode, MAY_READWRITE, rc);
 
        if (rc == 0 && new_dentry->d_inode != NULL) {
                isp = smk_of_inode(new_dentry->d_inode);
                smk_ad_setfield_u_fs_path_dentry(&ad, new_dentry);
                rc = smk_curacc(isp, MAY_READWRITE, &ad);
+               rc = smk_bu_inode(new_dentry->d_inode, MAY_READWRITE, rc);
        }
        return rc;
 }
@@ -820,6 +1010,7 @@ static int smack_inode_permission(struct inode *inode, int mask)
 {
        struct smk_audit_info ad;
        int no_block = mask & MAY_NOT_BLOCK;
+       int rc;
 
        mask &= (MAY_READ|MAY_WRITE|MAY_EXEC|MAY_APPEND);
        /*
@@ -833,7 +1024,9 @@ static int smack_inode_permission(struct inode *inode, int mask)
                return -ECHILD;
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_INODE);
        smk_ad_setfield_u_fs_inode(&ad, inode);
-       return smk_curacc(smk_of_inode(inode), mask, &ad);
+       rc = smk_curacc(smk_of_inode(inode), mask, &ad);
+       rc = smk_bu_inode(inode, mask, rc);
+       return rc;
 }
 
 /**
@@ -846,6 +1039,8 @@ static int smack_inode_permission(struct inode *inode, int mask)
 static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
 {
        struct smk_audit_info ad;
+       int rc;
+
        /*
         * Need to allow for clearing the setuid bit.
         */
@@ -854,7 +1049,9 @@ static int smack_inode_setattr(struct dentry *dentry, struct iattr *iattr)
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
        smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
-       return smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
+       rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
+       rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
+       return rc;
 }
 
 /**
@@ -868,13 +1065,17 @@ static int smack_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
 {
        struct smk_audit_info ad;
        struct path path;
+       int rc;
 
        path.dentry = dentry;
        path.mnt = mnt;
 
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
        smk_ad_setfield_u_fs_path(&ad, path);
-       return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
+
+       rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
+       rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc);
+       return rc;
 }
 
 /**
@@ -933,8 +1134,10 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
        smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
-       if (rc == 0)
+       if (rc == 0) {
                rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
+               rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
+       }
 
        return rc;
 }
@@ -994,11 +1197,14 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
 static int smack_inode_getxattr(struct dentry *dentry, const char *name)
 {
        struct smk_audit_info ad;
+       int rc;
 
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
        smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
-       return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
+       rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad);
+       rc = smk_bu_inode(dentry->d_inode, MAY_READ, rc);
+       return rc;
 }
 
 /**
@@ -1034,6 +1240,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
        smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
        rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
+       rc = smk_bu_inode(dentry->d_inode, MAY_WRITE, rc);
        if (rc != 0)
                return rc;
 
@@ -1215,11 +1422,15 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
        smk_ad_setfield_u_fs_path(&ad, file->f_path);
 
-       if (_IOC_DIR(cmd) & _IOC_WRITE)
+       if (_IOC_DIR(cmd) & _IOC_WRITE) {
                rc = smk_curacc(file->f_security, MAY_WRITE, &ad);
+               rc = smk_bu_file(file, MAY_WRITE, rc);
+       }
 
-       if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ))
-               rc = smk_curacc(file->f_security, MAY_READ, &ad);
+       if (rc == 0 && (_IOC_DIR(cmd) & _IOC_READ)) {
+               rc = smk_curacc(file->f_security, MAY_READ, &ad);
+               rc = smk_bu_file(file, MAY_READ, rc);
+       }
 
        return rc;
 }
@@ -1234,10 +1445,13 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
 static int smack_file_lock(struct file *file, unsigned int cmd)
 {
        struct smk_audit_info ad;
+       int rc;
 
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
        smk_ad_setfield_u_fs_path(&ad, file->f_path);
-       return smk_curacc(file->f_security, MAY_LOCK, &ad);
+       rc = smk_curacc(file->f_security, MAY_LOCK, &ad);
+       rc = smk_bu_file(file, MAY_LOCK, rc);
+       return rc;
 }
 
 /**
@@ -1267,12 +1481,14 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
                smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
                smk_ad_setfield_u_fs_path(&ad, file->f_path);
                rc = smk_curacc(file->f_security, MAY_LOCK, &ad);
+               rc = smk_bu_file(file, MAY_LOCK, rc);
                break;
        case F_SETOWN:
        case F_SETSIG:
                smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
                smk_ad_setfield_u_fs_path(&ad, file->f_path);
                rc = smk_curacc(file->f_security, MAY_WRITE, &ad);
+               rc = smk_bu_file(file, MAY_WRITE, rc);
                break;
        default:
                break;
@@ -1427,6 +1643,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
        /* we don't log here as rc can be overriden */
        skp = smk_find_entry(file->f_security);
        rc = smk_access(skp, tkp->smk_known, MAY_WRITE, NULL);
+       rc = smk_bu_note("sigiotask", skp, tkp->smk_known, MAY_WRITE, rc);
        if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
                rc = 0;
 
@@ -1444,6 +1661,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
  */
 static int smack_file_receive(struct file *file)
 {
+       int rc;
        int may = 0;
        struct smk_audit_info ad;
 
@@ -1457,7 +1675,9 @@ static int smack_file_receive(struct file *file)
        if (file->f_mode & FMODE_WRITE)
                may |= MAY_WRITE;
 
-       return smk_curacc(file->f_security, may, &ad);
+       rc = smk_curacc(file->f_security, may, &ad);
+       rc = smk_bu_file(file, may, rc);
+       return rc;
 }
 
 /**
@@ -1487,6 +1707,7 @@ static int smack_file_open(struct file *file, const struct cred *cred)
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
        smk_ad_setfield_u_fs_path(&ad, file->f_path);
        rc = smk_access(tsp->smk_task, isp->smk_inode, MAY_READ, &ad);
+       rc = smk_bu_credfile(cred, file, MAY_READ, rc);
        if (rc == 0)
                file->f_security = isp->smk_inode;
 
@@ -1643,10 +1864,13 @@ static int smk_curacc_on_task(struct task_struct *p, int access,
 {
        struct smk_audit_info ad;
        struct smack_known *skp = smk_of_task(task_security(p));
+       int rc;
 
        smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK);
        smk_ad_setfield_u_tsk(&ad, p);
-       return smk_curacc(skp->smk_known, access, &ad);
+       rc = smk_curacc(skp->smk_known, access, &ad);
+       rc = smk_bu_task(p, access, rc);
+       return rc;
 }
 
 /**
@@ -1800,6 +2024,7 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
        struct smk_audit_info ad;
        struct smack_known *skp;
        struct smack_known *tkp = smk_of_task(task_security(p));
+       int rc;
 
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
        smk_ad_setfield_u_tsk(&ad, p);
@@ -1807,15 +2032,20 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info,
         * Sending a signal requires that the sender
         * can write the receiver.
         */
-       if (secid == 0)
-               return smk_curacc(tkp->smk_known, MAY_WRITE, &ad);
+       if (secid == 0) {
+               rc = smk_curacc(tkp->smk_known, MAY_WRITE, &ad);
+               rc = smk_bu_task(p, MAY_WRITE, rc);
+               return rc;
+       }
        /*
         * If the secid isn't 0 we're dealing with some USB IO
         * specific behavior. This is not clean. For one thing
         * we can't take privilege into account.
         */
        skp = smack_from_secid(secid);
-       return smk_access(skp, tkp->smk_known, MAY_WRITE, &ad);
+       rc = smk_access(skp, tkp->smk_known, MAY_WRITE, &ad);
+       rc = smk_bu_note("USB signal", skp, tkp->smk_known, MAY_WRITE, rc);
+       return rc;
 }
 
 /**
@@ -2007,6 +2237,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
                sk_lbl = SMACK_UNLABELED_SOCKET;
                skp = ssp->smk_out;
                rc = smk_access(skp, hostsp, MAY_WRITE, &ad);
+               rc = smk_bu_note("IPv4 host check", skp, hostsp, MAY_WRITE, rc);
        } else {
                sk_lbl = SMACK_CIPSO_SOCKET;
                rc = 0;
@@ -2109,6 +2340,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
        unsigned short port = 0;
        char *object;
        struct smk_audit_info ad;
+       int rc;
 #ifdef CONFIG_AUDIT
        struct lsm_network_audit net;
 #endif
@@ -2162,7 +2394,9 @@ auditout:
        else
                ad.a.u.net->v6info.daddr = address->sin6_addr;
 #endif
-       return smk_access(skp, object, MAY_WRITE, &ad);
+       rc = smk_access(skp, object, MAY_WRITE, &ad);
+       rc = smk_bu_note("IPv6 port check", skp, object, MAY_WRITE, rc);
+       return rc;
 }
 
 /**
@@ -2401,12 +2635,15 @@ static int smk_curacc_shm(struct shmid_kernel *shp, int access)
 {
        char *ssp = smack_of_shm(shp);
        struct smk_audit_info ad;
+       int rc;
 
 #ifdef CONFIG_AUDIT
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
        ad.a.u.ipc_id = shp->shm_perm.id;
 #endif
-       return smk_curacc(ssp, access, &ad);
+       rc = smk_curacc(ssp, access, &ad);
+       rc = smk_bu_current("shm", ssp, access, rc);
+       return rc;
 }
 
 /**
@@ -2525,12 +2762,15 @@ static int smk_curacc_sem(struct sem_array *sma, int access)
 {
        char *ssp = smack_of_sem(sma);
        struct smk_audit_info ad;
+       int rc;
 
 #ifdef CONFIG_AUDIT
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
        ad.a.u.ipc_id = sma->sem_perm.id;
 #endif
-       return smk_curacc(ssp, access, &ad);
+       rc = smk_curacc(ssp, access, &ad);
+       rc = smk_bu_current("sem", ssp, access, rc);
+       return rc;
 }
 
 /**
@@ -2655,12 +2895,15 @@ static int smk_curacc_msq(struct msg_queue *msq, int access)
 {
        char *msp = smack_of_msq(msq);
        struct smk_audit_info ad;
+       int rc;
 
 #ifdef CONFIG_AUDIT
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
        ad.a.u.ipc_id = msq->q_perm.id;
 #endif
-       return smk_curacc(msp, access, &ad);
+       rc = smk_curacc(msp, access, &ad);
+       rc = smk_bu_current("msq", msp, access, rc);
+       return rc;
 }
 
 /**
@@ -2756,12 +2999,15 @@ static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag)
        char *isp = ipp->security;
        int may = smack_flags_to_may(flag);
        struct smk_audit_info ad;
+       int rc;
 
 #ifdef CONFIG_AUDIT
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
        ad.a.u.ipc_id = ipp->id;
 #endif
-       return smk_curacc(isp, may, &ad);
+       rc = smk_curacc(isp, may, &ad);
+       rc = smk_bu_current("svipc", isp, may, rc);
+       return rc;
 }
 
 /**
@@ -3094,6 +3340,8 @@ static int smack_unix_stream_connect(struct sock *sock,
                smk_ad_setfield_u_net_sk(&ad, other);
 #endif
                rc = smk_access(skp, okp->smk_known, MAY_WRITE, &ad);
+               rc = smk_bu_note("UDS connect", skp, okp->smk_known,
+                                       MAY_WRITE, rc);
        }
 
        /*
@@ -3121,6 +3369,7 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
        struct socket_smack *osp = other->sk->sk_security;
        struct smack_known *skp;
        struct smk_audit_info ad;
+       int rc;
 
 #ifdef CONFIG_AUDIT
        struct lsm_network_audit net;
@@ -3133,7 +3382,10 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other)
                return 0;
 
        skp = ssp->smk_out;
-       return smk_access(skp, osp->smk_in->smk_known, MAY_WRITE, &ad);
+       rc = smk_access(skp, osp->smk_in->smk_known, MAY_WRITE, &ad);
+       rc = smk_bu_note("UDS send", skp, osp->smk_in->smk_known,
+                               MAY_WRITE, rc);
+       return rc;
 }
 
 /**
@@ -3348,6 +3600,8 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                 * for networking.
                 */
                rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad);
+               rc = smk_bu_note("IPv4 delivery", skp, ssp->smk_in->smk_known,
+                                       MAY_WRITE, rc);
                if (rc != 0)
                        netlbl_skbuff_err(skb, rc, 0);
                break;
@@ -3528,6 +3782,8 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
         * here. Read access is not required.
         */
        rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad);
+       rc = smk_bu_note("IPv4 connect", skp, ssp->smk_in->smk_known,
+                               MAY_WRITE, rc);
        if (rc != 0)
                return rc;
 
@@ -3630,6 +3886,7 @@ static int smack_key_permission(key_ref_t key_ref,
        struct key *keyp;
        struct smk_audit_info ad;
        struct smack_known *tkp = smk_of_task(cred->security);
+       int rc;
 
        keyp = key_ref_to_ptr(key_ref);
        if (keyp == NULL)
@@ -3650,7 +3907,9 @@ static int smack_key_permission(key_ref_t key_ref,
        ad.a.u.key_struct.key = keyp->serial;
        ad.a.u.key_struct.key_desc = keyp->description;
 #endif
-       return smk_access(tkp, keyp->security, MAY_READWRITE, &ad);
+       rc = smk_access(tkp, keyp->security, MAY_READWRITE, &ad);
+       rc = smk_bu_note("key access", tkp, keyp->security, MAY_READWRITE, rc);
+       return rc;
 }
 #endif /* CONFIG_KEYS */
 
index 39af4bf..978e9a5 100644 (file)
@@ -54,6 +54,9 @@ enum smk_inos {
        SMK_CHANGE_RULE = 19,   /* change or add rules (long labels) */
        SMK_SYSLOG      = 20,   /* change syslog label) */
        SMK_PTRACE      = 21,   /* set ptrace rule */
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+       SMK_UNCONFINED  = 22,   /* define an unconfined label */
+#endif
 };
 
 /*
@@ -95,6 +98,16 @@ int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
  */
 struct smack_known *smack_onlycap;
 
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+/*
+ * Allow one label to be unconfined. This is for
+ * debugging and application bring-up purposes only.
+ * It is bad and wrong, but everyone seems to expect
+ * to have it.
+ */
+struct smack_known *smack_unconfined;
+#endif
+
 /*
  * If this value is set restrict syslog use to the label specified.
  * It can be reset via smackfs/syslog
@@ -300,6 +313,10 @@ static int smk_perm_from_str(const char *string)
                case 'L':
                        perm |= MAY_LOCK;
                        break;
+               case 'b':
+               case 'B':
+                       perm |= MAY_BRINGUP;
+                       break;
                default:
                        return perm;
                }
@@ -612,6 +629,8 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
                seq_putc(s, 't');
        if (srp->smk_access & MAY_LOCK)
                seq_putc(s, 'l');
+       if (srp->smk_access & MAY_BRINGUP)
+               seq_putc(s, 'b');
 
        seq_putc(s, '\n');
 }
@@ -1702,6 +1721,85 @@ static const struct file_operations smk_onlycap_ops = {
        .llseek         = default_llseek,
 };
 
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+/**
+ * smk_read_unconfined - read() for smackfs/unconfined
+ * @filp: file pointer, not actually used
+ * @buf: where to put the result
+ * @cn: maximum to send along
+ * @ppos: where to start
+ *
+ * Returns number of bytes read or error code, as appropriate
+ */
+static ssize_t smk_read_unconfined(struct file *filp, char __user *buf,
+                                       size_t cn, loff_t *ppos)
+{
+       char *smack = "";
+       ssize_t rc = -EINVAL;
+       int asize;
+
+       if (*ppos != 0)
+               return 0;
+
+       if (smack_unconfined != NULL)
+               smack = smack_unconfined->smk_known;
+
+       asize = strlen(smack) + 1;
+
+       if (cn >= asize)
+               rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
+
+       return rc;
+}
+
+/**
+ * smk_write_unconfined - write() for smackfs/unconfined
+ * @file: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start
+ *
+ * Returns number of bytes written or error code, as appropriate
+ */
+static ssize_t smk_write_unconfined(struct file *file, const char __user *buf,
+                                       size_t count, loff_t *ppos)
+{
+       char *data;
+       int rc = count;
+
+       if (!smack_privileged(CAP_MAC_ADMIN))
+               return -EPERM;
+
+       data = kzalloc(count + 1, GFP_KERNEL);
+       if (data == NULL)
+               return -ENOMEM;
+
+       /*
+        * Should the null string be passed in unset the unconfined value.
+        * This seems like something to be careful with as usually
+        * smk_import only expects to return NULL for errors. It
+        * is usually the case that a nullstring or "\n" would be
+        * bad to pass to smk_import but in fact this is useful here.
+        *
+        * smk_import will also reject a label beginning with '-',
+        * so "-confine" will also work.
+        */
+       if (copy_from_user(data, buf, count) != 0)
+               rc = -EFAULT;
+       else
+               smack_unconfined = smk_import_entry(data, count);
+
+       kfree(data);
+       return rc;
+}
+
+static const struct file_operations smk_unconfined_ops = {
+       .read           = smk_read_unconfined,
+       .write          = smk_write_unconfined,
+       .llseek         = default_llseek,
+};
+#endif /* CONFIG_SECURITY_SMACK_BRINGUP */
+
 /**
  * smk_read_logging - read() for /smack/logging
  * @filp: file pointer, not actually used
@@ -1876,7 +1974,11 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf,
        else if (res != -ENOENT)
                return -EINVAL;
 
-       data[0] = res == 0 ? '1' : '0';
+       /*
+        * smk_access() can return a value > 0 in the "bringup" case.
+        */
+       data[0] = res >= 0 ? '1' : '0';
+
        data[1] = '\0';
 
        simple_transaction_set(file, 2);
@@ -2366,6 +2468,10 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
                        "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR},
                [SMK_PTRACE] = {
                        "ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR},
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+               [SMK_UNCONFINED] = {
+                       "unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR},
+#endif
                /* last one */
                        {""}
        };