Merge branch 'next' of git://git.infradead.org/users/pcmoore/selinux into next
authorJames Morris <james.l.morris@oracle.com>
Mon, 26 May 2014 12:38:46 +0000 (22:38 +1000)
committerJames Morris <james.l.morris@oracle.com>
Mon, 26 May 2014 12:38:46 +0000 (22:38 +1000)
46 files changed:
Documentation/security/Smack.txt
MAINTAINERS
include/linux/fs.h
include/linux/key.h
include/linux/security.h
kernel/capability.c
kernel/seccomp.c
security/Makefile
security/apparmor/lsm.c
security/capability.c
security/integrity/Makefile
security/integrity/evm/Kconfig
security/integrity/evm/evm.h
security/integrity/evm/evm_crypto.c
security/integrity/evm/evm_main.c
security/integrity/evm/evm_secfs.c
security/integrity/iint.c
security/integrity/ima/ima.h
security/integrity/ima/ima_api.c
security/integrity/ima/ima_appraise.c
security/integrity/ima/ima_crypto.c
security/integrity/ima/ima_fs.c
security/integrity/ima/ima_init.c
security/integrity/ima/ima_main.c
security/integrity/ima/ima_policy.c
security/integrity/ima/ima_queue.c
security/integrity/ima/ima_template.c
security/integrity/ima/ima_template_lib.c
security/integrity/integrity_audit.c
security/keys/encrypted-keys/encrypted.c
security/keys/internal.h
security/keys/key.c
security/keys/keyctl.c
security/keys/keyring.c
security/keys/permission.c
security/keys/persistent.c
security/keys/proc.c
security/keys/sysctl.c
security/keys/trusted.c
security/security.c
security/selinux/hooks.c
security/selinux/selinuxfs.c
security/smack/smack.h
security/smack/smack_access.c
security/smack/smack_lsm.c
security/smack/smackfs.c

index 7a2d30c132e3fb26d6ab4eae14f361028370ed7a..5597917703e08080783cc4cbfe558f350cac6521 100644 (file)
@@ -204,6 +204,16 @@ onlycap
        these capabilities are effective at for processes with any
        label. The value is set by writing the desired label to the
        file or cleared by writing "-" to the file.
+ptrace
+       This is used to define the current ptrace policy
+       0 - default: this is the policy that relies on smack access rules.
+           For the PTRACE_READ a subject needs to have a read access on
+           object. For the PTRACE_ATTACH a read-write access is required.
+       1 - exact: this is the policy that limits PTRACE_ATTACH. Attach is
+           only allowed when subject's and object's labels are equal.
+           PTRACE_READ is not affected. Can be overriden with CAP_SYS_PTRACE.
+       2 - draconian: this policy behaves like the 'exact' above with an
+           exception that it can't be overriden with CAP_SYS_PTRACE.
 revoke-subject
        Writing a Smack label here sets the access to '-' for all access
        rules with that subject label.
index ae2e14142253ac17677c0248fac110edcbeb42db..1c323b0290cd1760441f0f39c36d6739c48070e4 100644 (file)
@@ -3380,7 +3380,9 @@ F:        Documentation/filesystems/ext4.txt
 F:     fs/ext4/
 
 Extended Verification Module (EVM)
-M:     Mimi Zohar <zohar@us.ibm.com>
+M:     Mimi Zohar <zohar@linux.vnet.ibm.com>
+L:     linux-ima-devel@lists.sourceforge.net
+L:     linux-security-module@vger.kernel.org
 S:     Supported
 F:     security/integrity/evm/
 
@@ -4402,8 +4404,11 @@ S:       Maintained
 F:     drivers/ipack/
 
 INTEGRITY MEASUREMENT ARCHITECTURE (IMA)
-M:     Mimi Zohar <zohar@us.ibm.com>
+M:     Mimi Zohar <zohar@linux.vnet.ibm.com>
 M:     Dmitry Kasatkin <d.kasatkin@samsung.com>
+L:     linux-ima-devel@lists.sourceforge.net
+L:     linux-ima-user@lists.sourceforge.net
+L:     linux-security-module@vger.kernel.org
 S:     Supported
 F:     security/integrity/ima/
 
@@ -5071,8 +5076,8 @@ F:        include/keys/
 F:     security/keys/
 
 KEYS-TRUSTED
-M:     David Safford <safford@watson.ibm.com>
-M:     Mimi Zohar <zohar@us.ibm.com>
+M:     David Safford <safford@us.ibm.com>
+M:     Mimi Zohar <zohar@linux.vnet.ibm.com>
 L:     linux-security-module@vger.kernel.org
 L:     keyrings@linux-nfs.org
 S:     Supported
@@ -5082,8 +5087,8 @@ F:        security/keys/trusted.c
 F:     security/keys/trusted.h
 
 KEYS-ENCRYPTED
-M:     Mimi Zohar <zohar@us.ibm.com>
-M:     David Safford <safford@watson.ibm.com>
+M:     Mimi Zohar <zohar@linux.vnet.ibm.com>
+M:     David Safford <safford@us.ibm.com>
 L:     linux-security-module@vger.kernel.org
 L:     keyrings@linux-nfs.org
 S:     Supported
index 23b2a35d712efbec3e31df0cae70b69a17b81616..6e765d28841b260aedb2668cfbdd1719818245e4 100644 (file)
@@ -589,6 +589,9 @@ struct inode {
        atomic_t                i_count;
        atomic_t                i_dio_count;
        atomic_t                i_writecount;
+#ifdef CONFIG_IMA
+       atomic_t                i_readcount; /* struct files open RO */
+#endif
        const struct file_operations    *i_fop; /* former ->i_op->default_file_ops */
        struct file_lock        *i_flock;
        struct address_space    i_data;
@@ -609,9 +612,6 @@ struct inode {
        struct hlist_head       i_fsnotify_marks;
 #endif
 
-#ifdef CONFIG_IMA
-       atomic_t                i_readcount; /* struct files open RO */
-#endif
        void                    *i_private; /* fs or device private pointer */
 };
 
index 80d677483e31f95ce4b08ef00ffb79c239932c18..cd0abb8c9c33de3ce139632340de1c19381f9780 100644 (file)
@@ -309,6 +309,17 @@ static inline key_serial_t key_serial(const struct key *key)
 
 extern void key_set_timeout(struct key *, unsigned);
 
+/*
+ * The permissions required on a key that we're looking up.
+ */
+#define        KEY_NEED_VIEW   0x01    /* Require permission to view attributes */
+#define        KEY_NEED_READ   0x02    /* Require permission to read content */
+#define        KEY_NEED_WRITE  0x04    /* Require permission to update / modify */
+#define        KEY_NEED_SEARCH 0x08    /* Require permission to search (keyring) or find (key) */
+#define        KEY_NEED_LINK   0x10    /* Require permission to link */
+#define        KEY_NEED_SETATTR 0x20   /* Require permission to change attributes */
+#define        KEY_NEED_ALL    0x3f    /* All the above permissions */
+
 /**
  * key_is_instantiated - Determine if a key has been positively instantiated
  * @key: The key to check.
index 2fc42d191f79f77236b843a70775129c01207333..6726006bc766596deee7d14f52220d29c3ebccbe 100644 (file)
@@ -1708,7 +1708,7 @@ struct security_operations {
        void (*key_free) (struct key *key);
        int (*key_permission) (key_ref_t key_ref,
                               const struct cred *cred,
-                              key_perm_t perm);
+                              unsigned perm);
        int (*key_getsecurity)(struct key *key, char **_buffer);
 #endif /* CONFIG_KEYS */
 
@@ -3030,7 +3030,7 @@ static inline int security_path_chroot(struct path *path)
 int security_key_alloc(struct key *key, const struct cred *cred, unsigned long flags);
 void security_key_free(struct key *key);
 int security_key_permission(key_ref_t key_ref,
-                           const struct cred *cred, key_perm_t perm);
+                           const struct cred *cred, unsigned perm);
 int security_key_getsecurity(struct key *key, char **_buffer);
 
 #else
@@ -3048,7 +3048,7 @@ static inline void security_key_free(struct key *key)
 
 static inline int security_key_permission(key_ref_t key_ref,
                                          const struct cred *cred,
-                                         key_perm_t perm)
+                                         unsigned perm)
 {
        return 0;
 }
index 34019c57888d4d093956b81963b557abd95103e9..a8d63df0c322491165d32d66db542781a7e27f99 100644 (file)
@@ -7,6 +7,8 @@
  * 30 May 2002:        Cleanup, Robert M. Love <rml@tech9.net>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/audit.h>
 #include <linux/capability.h>
 #include <linux/mm.h>
@@ -42,15 +44,10 @@ __setup("no_file_caps", file_caps_disable);
 
 static void warn_legacy_capability_use(void)
 {
-       static int warned;
-       if (!warned) {
-               char name[sizeof(current->comm)];
-
-               printk(KERN_INFO "warning: `%s' uses 32-bit capabilities"
-                      " (legacy support in use)\n",
-                      get_task_comm(name, current));
-               warned = 1;
-       }
+       char name[sizeof(current->comm)];
+
+       pr_info_once("warning: `%s' uses 32-bit capabilities (legacy support in use)\n",
+                    get_task_comm(name, current));
 }
 
 /*
@@ -71,16 +68,10 @@ static void warn_legacy_capability_use(void)
 
 static void warn_deprecated_v2(void)
 {
-       static int warned;
+       char name[sizeof(current->comm)];
 
-       if (!warned) {
-               char name[sizeof(current->comm)];
-
-               printk(KERN_INFO "warning: `%s' uses deprecated v2"
-                      " capabilities in a way that may be insecure.\n",
-                      get_task_comm(name, current));
-               warned = 1;
-       }
+       pr_info_once("warning: `%s' uses deprecated v2 capabilities in a way that may be insecure\n",
+                    get_task_comm(name, current));
 }
 
 /*
@@ -380,7 +371,7 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
 bool ns_capable(struct user_namespace *ns, int cap)
 {
        if (unlikely(!cap_valid(cap))) {
-               printk(KERN_CRIT "capable() called with invalid cap=%u\n", cap);
+               pr_crit("capable() called with invalid cap=%u\n", cap);
                BUG();
        }
 
index b7a10048a32c11fb473515d9075ef2b0782a563a..0e004a70f63a572d751b95cbdef8316ce1e22053 100644 (file)
@@ -293,7 +293,7 @@ fail:
  *
  * Returns 0 on success and non-zero otherwise.
  */
-long seccomp_attach_user_filter(char __user *user_filter)
+static long seccomp_attach_user_filter(char __user *user_filter)
 {
        struct sock_fprog fprog;
        long ret = -EFAULT;
index a5918e01a4f71a6e97abc664682bd23f75bc544f..05f1c934d74bda522fb54318b33d1f206d5860ba 100644 (file)
@@ -16,14 +16,14 @@ obj-$(CONFIG_MMU)                   += min_addr.o
 # Object file lists
 obj-$(CONFIG_SECURITY)                 += security.o capability.o
 obj-$(CONFIG_SECURITYFS)               += inode.o
-obj-$(CONFIG_SECURITY_SELINUX)         += selinux/built-in.o
-obj-$(CONFIG_SECURITY_SMACK)           += smack/built-in.o
+obj-$(CONFIG_SECURITY_SELINUX)         += selinux/
+obj-$(CONFIG_SECURITY_SMACK)           += smack/
 obj-$(CONFIG_AUDIT)                    += lsm_audit.o
-obj-$(CONFIG_SECURITY_TOMOYO)          += tomoyo/built-in.o
-obj-$(CONFIG_SECURITY_APPARMOR)                += apparmor/built-in.o
-obj-$(CONFIG_SECURITY_YAMA)            += yama/built-in.o
+obj-$(CONFIG_SECURITY_TOMOYO)          += tomoyo/
+obj-$(CONFIG_SECURITY_APPARMOR)                += apparmor/
+obj-$(CONFIG_SECURITY_YAMA)            += yama/
 obj-$(CONFIG_CGROUP_DEVICE)            += device_cgroup.o
 
 # Object integrity file lists
 subdir-$(CONFIG_INTEGRITY)             += integrity
-obj-$(CONFIG_INTEGRITY)                        += integrity/built-in.o
+obj-$(CONFIG_INTEGRITY)                        += integrity/
index 4257b7e2796bf16e41db9ddca0e1f7c8e0d08a02..998100093332a1390d1bc26b07eab91307fa2917 100644 (file)
@@ -751,7 +751,7 @@ module_param_named(enabled, apparmor_enabled, bool, S_IRUGO);
 static int __init apparmor_enabled_setup(char *str)
 {
        unsigned long enabled;
-       int error = strict_strtoul(str, 0, &enabled);
+       int error = kstrtoul(str, 0, &enabled);
        if (!error)
                apparmor_enabled = enabled ? 1 : 0;
        return 1;
index 21e2b9cae685f01536ed159443707d5046c8c34c..e76373de31298e0a3264920035374b849bc42fb1 100644 (file)
@@ -116,7 +116,7 @@ static int cap_dentry_init_security(struct dentry *dentry, int mode,
                                        struct qstr *name, void **ctx,
                                        u32 *ctxlen)
 {
-       return 0;
+       return -EOPNOTSUPP;
 }
 
 static int cap_inode_alloc_security(struct inode *inode)
@@ -879,7 +879,7 @@ static void cap_key_free(struct key *key)
 }
 
 static int cap_key_permission(key_ref_t key_ref, const struct cred *cred,
-                             key_perm_t perm)
+                             unsigned perm)
 {
        return 0;
 }
index 0f9cffb1f9ade08400a916d7a5e3694679266e49..0793f4811cb7d6644def01b8563d8bc913619fe0 100644 (file)
@@ -10,6 +10,6 @@ obj-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
 integrity-y := iint.o
 
 subdir-$(CONFIG_IMA)                   += ima
-obj-$(CONFIG_IMA)                      += ima/built-in.o
+obj-$(CONFIG_IMA)                      += ima/
 subdir-$(CONFIG_EVM)                   += evm
-obj-$(CONFIG_EVM)                      += evm/built-in.o
+obj-$(CONFIG_EVM)                      += evm/
index fea9749c37562b1006885cf56410361a64f31db1..d35b4915b00d4722e76464baba6b272ce86332f0 100644 (file)
@@ -1,10 +1,10 @@
 config EVM
        boolean "EVM support"
-       depends on SECURITY && KEYS && (TRUSTED_KEYS=y || TRUSTED_KEYS=n)
+       depends on SECURITY
+       select KEYS
+       select ENCRYPTED_KEYS
        select CRYPTO_HMAC
-       select CRYPTO_MD5
        select CRYPTO_SHA1
-       select ENCRYPTED_KEYS
        default n
        help
          EVM protects a file's security extended attributes against
index 30bd1ec0232e1ddd2a7d7585e752ae6c6bedcdc9..37c88ddb3cfe459e88822742e3cd25b15fb6f992 100644 (file)
@@ -32,19 +32,19 @@ extern struct crypto_shash *hash_tfm;
 /* List of EVM protected security xattrs */
 extern char *evm_config_xattrnames[];
 
-extern int evm_init_key(void);
-extern int evm_update_evmxattr(struct dentry *dentry,
-                              const char *req_xattr_name,
-                              const char *req_xattr_value,
-                              size_t req_xattr_value_len);
-extern int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
-                        const char *req_xattr_value,
-                        size_t req_xattr_value_len, char *digest);
-extern int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
-                        const char *req_xattr_value,
-                        size_t req_xattr_value_len, char *digest);
-extern int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
-                        char *hmac_val);
-extern int evm_init_secfs(void);
+int evm_init_key(void);
+int evm_update_evmxattr(struct dentry *dentry,
+                       const char *req_xattr_name,
+                       const char *req_xattr_value,
+                       size_t req_xattr_value_len);
+int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name,
+                 const char *req_xattr_value,
+                 size_t req_xattr_value_len, char *digest);
+int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name,
+                 const char *req_xattr_value,
+                 size_t req_xattr_value_len, char *digest);
+int evm_init_hmac(struct inode *inode, const struct xattr *xattr,
+                 char *hmac_val);
+int evm_init_secfs(void);
 
 #endif
index 3bab89eb21d608b1123b97188234137db83869b8..babd8626bf968f584153518d7ecb60e9a4616d39 100644 (file)
@@ -13,6 +13,8 @@
  *      Using root's kernel master key (kmk), calculate the HMAC
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/crypto.h>
 #include <linux/xattr.h>
@@ -103,13 +105,13 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,
                umode_t mode;
        } hmac_misc;
 
-       memset(&hmac_misc, 0, sizeof hmac_misc);
+       memset(&hmac_misc, 0, sizeof(hmac_misc));
        hmac_misc.ino = inode->i_ino;
        hmac_misc.generation = inode->i_generation;
        hmac_misc.uid = from_kuid(&init_user_ns, inode->i_uid);
        hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid);
        hmac_misc.mode = inode->i_mode;
-       crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof hmac_misc);
+       crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof(hmac_misc));
        if (evm_hmac_version > 1)
                crypto_shash_update(desc, inode->i_sb->s_uuid,
                                    sizeof(inode->i_sb->s_uuid));
@@ -221,7 +223,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr,
 
        desc = init_desc(EVM_XATTR_HMAC);
        if (IS_ERR(desc)) {
-               printk(KERN_INFO "init_desc failed\n");
+               pr_info("init_desc failed\n");
                return PTR_ERR(desc);
        }
 
index 336b3ddfe63f5304374f860419cd3f5251bde5b8..996092f21b64a4b71ee1a46acc49a94802e7618e 100644 (file)
@@ -14,6 +14,8 @@
  *     evm_inode_removexattr, and evm_verifyxattr
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/crypto.h>
 #include <linux/audit.h>
@@ -432,7 +434,7 @@ static int __init init_evm(void)
 
        error = evm_init_secfs();
        if (error < 0) {
-               printk(KERN_INFO "EVM: Error registering secfs\n");
+               pr_info("Error registering secfs\n");
                goto err;
        }
 
@@ -449,7 +451,7 @@ static int __init evm_display_config(void)
        char **xattrname;
 
        for (xattrname = evm_config_xattrnames; *xattrname != NULL; xattrname++)
-               printk(KERN_INFO "EVM: %s\n", *xattrname);
+               pr_info("%s\n", *xattrname);
        return 0;
 }
 
index 30f670ad6ac3a63ce98db857ad812eab144d6419..cf12a04717d32d8ab8e90d94c0aa39cc282abc3a 100644 (file)
@@ -13,6 +13,8 @@
  *     - Get the key and enable EVM
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/uaccess.h>
 #include <linux/module.h>
 #include "evm.h"
@@ -79,9 +81,9 @@ static ssize_t evm_write_key(struct file *file, const char __user *buf,
        error = evm_init_key();
        if (!error) {
                evm_initialized = 1;
-               pr_info("EVM: initialized\n");
+               pr_info("initialized\n");
        } else
-               pr_err("EVM: initialization failed\n");
+               pr_err("initialization failed\n");
        return count;
 }
 
index c49d3f14cbec96b49e2b8bedf15b4be570c5a7ef..a521edf4cbd62ff1b3a3f878976826576c01d2f7 100644 (file)
@@ -151,7 +151,7 @@ static void init_once(void *foo)
 {
        struct integrity_iint_cache *iint = foo;
 
-       memset(iint, 0, sizeof *iint);
+       memset(iint, 0, sizeof(*iint));
        iint->version = 0;
        iint->flags = 0UL;
        iint->ima_file_status = INTEGRITY_UNKNOWN;
index 0356e1d437ca31cde30910567128168dbfd0a5ca..f79fa8be203cd3703ad1a7fedddfe7037f602cdd 100644 (file)
@@ -27,7 +27,7 @@
 #include "../integrity.h"
 
 enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN,
-                    IMA_SHOW_ASCII };
+                    IMA_SHOW_BINARY_OLD_STRING_FMT, IMA_SHOW_ASCII };
 enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
 
 /* digest size for IMA, fits SHA1 or MD5 */
index c38bbce8c6a629e246d8f6bef7557e224707d88b..ba9e4d792dd577acd3662ade0928b55fdc02d21b 100644 (file)
@@ -92,8 +92,8 @@ int ima_store_template(struct ima_template_entry *entry,
                       int violation, struct inode *inode,
                       const unsigned char *filename)
 {
-       const char *op = "add_template_measure";
-       const char *audit_cause = "hashing_error";
+       static const char op[] = "add_template_measure";
+       static const char audit_cause[] = "hashing_error";
        char *template_name = entry->template_desc->name;
        int result;
        struct {
@@ -132,7 +132,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
                       const char *op, const char *cause)
 {
        struct ima_template_entry *entry;
-       struct inode *inode = file->f_dentry->d_inode;
+       struct inode *inode = file_inode(file);
        int violation = 1;
        int result;
 
@@ -160,10 +160,10 @@ err_out:
  * @function: calling function (FILE_CHECK, BPRM_CHECK, MMAP_CHECK, MODULE_CHECK)
  *
  * The policy is defined in terms of keypairs:
- *             subj=, obj=, type=, func=, mask=, fsmagic=
+ *             subj=, obj=, type=, func=, mask=, fsmagic=
  *     subj,obj, and type: are LSM specific.
- *     func: FILE_CHECK | BPRM_CHECK | MMAP_CHECK | MODULE_CHECK
- *     mask: contains the permission mask
+ *     func: FILE_CHECK | BPRM_CHECK | MMAP_CHECK | MODULE_CHECK
+ *     mask: contains the permission mask
  *     fsmagic: hex value
  *
  * Returns IMA_MEASURE, IMA_APPRAISE mask.
@@ -248,7 +248,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
  *
  * We only get here if the inode has not already been measured,
  * but the measurement could already exist:
- *     - multiple copies of the same file on either the same or
+ *     - multiple copies of the same file on either the same or
  *       different filesystems.
  *     - the inode was previously flushed as well as the iint info,
  *       containing the hashing info.
@@ -260,8 +260,8 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
                           struct evm_ima_xattr_data *xattr_value,
                           int xattr_len)
 {
-       const char *op = "add_template_measure";
-       const char *audit_cause = "ENOMEM";
+       static const char op[] = "add_template_measure";
+       static const char audit_cause[] = "ENOMEM";
        int result = -ENOMEM;
        struct inode *inode = file_inode(file);
        struct ima_template_entry *entry;
@@ -332,5 +332,5 @@ const char *ima_d_path(struct path *path, char **pathbuf)
                        pathname = NULL;
                }
        }
-       return pathname;
+       return pathname ?: (const char *)path->dentry->d_name.name;
 }
index 734e9468aca01c9a3724a57136f6d8bf371951f3..291bf0f3a46d7989c1d4cf77fdba0237a6d0fb1f 100644 (file)
@@ -177,11 +177,11 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
                             struct evm_ima_xattr_data *xattr_value,
                             int xattr_len)
 {
+       static const char op[] = "appraise_data";
+       char *cause = "unknown";
        struct dentry *dentry = file->f_dentry;
        struct inode *inode = dentry->d_inode;
        enum integrity_status status = INTEGRITY_UNKNOWN;
-       const char *op = "appraise_data";
-       char *cause = "unknown";
        int rc = xattr_len, hash_start = 0;
 
        if (!ima_appraise)
index fdf60def52e90c93799e7d6ff6298ab4dd68c6d3..1bde8e62776620e6e5ed2cb2900d39c91df992f8 100644 (file)
  * the Free Software Foundation, version 2 of the License.
  *
  * File: ima_crypto.c
- *     Calculates md5/sha1 file hash, template hash, boot-aggreate hash
+ *     Calculates md5/sha1 file hash, template hash, boot-aggreate hash
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/file.h>
 #include <linux/crypto.h>
@@ -85,16 +87,20 @@ static int ima_calc_file_hash_tfm(struct file *file,
        if (rc != 0)
                return rc;
 
-       rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
-       if (!rbuf) {
-               rc = -ENOMEM;
+       i_size = i_size_read(file_inode(file));
+
+       if (i_size == 0)
                goto out;
-       }
+
+       rbuf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+       if (!rbuf)
+               return -ENOMEM;
+
        if (!(file->f_mode & FMODE_READ)) {
                file->f_mode |= FMODE_READ;
                read = 1;
        }
-       i_size = i_size_read(file_inode(file));
+
        while (offset < i_size) {
                int rbuf_len;
 
@@ -111,12 +117,12 @@ static int ima_calc_file_hash_tfm(struct file *file,
                if (rc)
                        break;
        }
-       kfree(rbuf);
-       if (!rc)
-               rc = crypto_shash_final(&desc.shash, hash->digest);
        if (read)
                file->f_mode &= ~FMODE_READ;
+       kfree(rbuf);
 out:
+       if (!rc)
+               rc = crypto_shash_final(&desc.shash, hash->digest);
        return rc;
 }
 
@@ -161,15 +167,22 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data,
                return rc;
 
        for (i = 0; i < num_fields; i++) {
+               u8 buffer[IMA_EVENT_NAME_LEN_MAX + 1] = { 0 };
+               u8 *data_to_hash = field_data[i].data;
+               u32 datalen = field_data[i].len;
+
                if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) {
                        rc = crypto_shash_update(&desc.shash,
                                                (const u8 *) &field_data[i].len,
                                                sizeof(field_data[i].len));
                        if (rc)
                                break;
+               } else if (strcmp(td->fields[i]->field_id, "n") == 0) {
+                       memcpy(buffer, data_to_hash, datalen);
+                       data_to_hash = buffer;
+                       datalen = IMA_EVENT_NAME_LEN_MAX + 1;
                }
-               rc = crypto_shash_update(&desc.shash, field_data[i].data,
-                                        field_data[i].len);
+               rc = crypto_shash_update(&desc.shash, data_to_hash, datalen);
                if (rc)
                        break;
        }
@@ -205,7 +218,7 @@ static void __init ima_pcrread(int idx, u8 *pcr)
                return;
 
        if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0)
-               pr_err("IMA: Error Communicating to TPM chip\n");
+               pr_err("Error Communicating to TPM chip\n");
 }
 
 /*
index db01125926bdb1e696165389bcdd26117e9d25fc..da92fcc08d151645c8139ba724c9c15ccd029267 100644 (file)
@@ -133,14 +133,14 @@ static int ima_measurements_show(struct seq_file *m, void *v)
         * PCR used is always the same (config option) in
         * little-endian format
         */
-       ima_putc(m, &pcr, sizeof pcr);
+       ima_putc(m, &pcr, sizeof(pcr));
 
        /* 2nd: template digest */
        ima_putc(m, e->digest, TPM_DIGEST_SIZE);
 
        /* 3rd: template name size */
        namelen = strlen(e->template_desc->name);
-       ima_putc(m, &namelen, sizeof namelen);
+       ima_putc(m, &namelen, sizeof(namelen));
 
        /* 4th:  template name */
        ima_putc(m, e->template_desc->name, namelen);
@@ -160,6 +160,8 @@ static int ima_measurements_show(struct seq_file *m, void *v)
 
                if (is_ima_template && strcmp(field->field_id, "d") == 0)
                        show = IMA_SHOW_BINARY_NO_FIELD_LEN;
+               if (is_ima_template && strcmp(field->field_id, "n") == 0)
+                       show = IMA_SHOW_BINARY_OLD_STRING_FMT;
                field->field_show(m, show, &e->template_data[i]);
        }
        return 0;
@@ -290,7 +292,7 @@ static atomic_t policy_opencount = ATOMIC_INIT(1);
 /*
  * ima_open_policy: sequentialize access to the policy file
  */
-static int ima_open_policy(struct inode * inode, struct file * filp)
+static int ima_open_policy(struct inode *inode, struct file *filp)
 {
        /* No point in being allowed to open it if you aren't going to write */
        if (!(filp->f_flags & O_WRONLY))
index 37122768554a9e69d4866f9c9a72864f157afef3..e8f9d70a465d11168748967928e34491f46c1765 100644 (file)
@@ -14,6 +14,9 @@
  * File: ima_init.c
  *             initialization and cleanup functions
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
@@ -42,10 +45,10 @@ int ima_used_chip;
  */
 static void __init ima_add_boot_aggregate(void)
 {
+       static const char op[] = "add_boot_aggregate";
+       const char *audit_cause = "ENOMEM";
        struct ima_template_entry *entry;
        struct integrity_iint_cache tmp_iint, *iint = &tmp_iint;
-       const char *op = "add_boot_aggregate";
-       const char *audit_cause = "ENOMEM";
        int result = -ENOMEM;
        int violation = 0;
        struct {
@@ -93,7 +96,7 @@ int __init ima_init(void)
                ima_used_chip = 1;
 
        if (!ima_used_chip)
-               pr_info("IMA: No TPM chip found, activating TPM-bypass!\n");
+               pr_info("No TPM chip found, activating TPM-bypass!\n");
 
        rc = ima_init_crypto();
        if (rc)
index 149ee1119f87ba37c7673efdd7fd4d0e50cae809..52ac6cf41f880bec8360f42a6526213117bdbc43 100644 (file)
@@ -71,15 +71,14 @@ __setup("ima_hash=", hash_setup);
  * ima_rdwr_violation_check
  *
  * Only invalidate the PCR for measured files:
- *     - Opening a file for write when already open for read,
+ *     - Opening a file for write when already open for read,
  *       results in a time of measure, time of use (ToMToU) error.
  *     - Opening a file for read when already open for write,
- *       could result in a file measurement error.
+ *       could result in a file measurement error.
  *
  */
 static void ima_rdwr_violation_check(struct file *file)
 {
-       struct dentry *dentry = file->f_path.dentry;
        struct inode *inode = file_inode(file);
        fmode_t mode = file->f_mode;
        int must_measure;
@@ -111,8 +110,6 @@ out:
                return;
 
        pathname = ima_d_path(&file->f_path, &pathbuf);
-       if (!pathname || strlen(pathname) > IMA_EVENT_NAME_LEN_MAX)
-               pathname = dentry->d_name.name;
 
        if (send_tomtou)
                ima_add_violation(file, pathname, "invalid_pcr", "ToMToU");
@@ -220,9 +217,7 @@ static int process_measurement(struct file *file, const char *filename,
        if (rc != 0)
                goto out_digsig;
 
-       pathname = !filename ? ima_d_path(&file->f_path, &pathbuf) : filename;
-       if (!pathname)
-               pathname = (const char *)file->f_dentry->d_name.name;
+       pathname = filename ?: ima_d_path(&file->f_path, &pathbuf);
 
        if (action & IMA_MEASURE)
                ima_store_measurement(iint, file, pathname,
index a9c3d3cd1990d506a431614ffcf1d63ee53434a3..93873a450ff720ff47bf5ec92b23b179bb0628dd 100644 (file)
@@ -7,7 +7,7 @@
  * the Free Software Foundation, version 2 of the License.
  *
  * ima_policy.c
- *     - initialize default measure policy rules
+ *     - initialize default measure policy rules
  *
  */
 #include <linux/module.h>
@@ -21,8 +21,8 @@
 #include "ima.h"
 
 /* flags definitions */
-#define IMA_FUNC       0x0001
-#define IMA_MASK       0x0002
+#define IMA_FUNC       0x0001
+#define IMA_MASK       0x0002
 #define IMA_FSMAGIC    0x0004
 #define IMA_UID                0x0008
 #define IMA_FOWNER     0x0010
@@ -69,35 +69,35 @@ struct ima_rule_entry {
  * and running executables.
  */
 static struct ima_rule_entry default_rules[] = {
-       {.action = DONT_MEASURE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_MEASURE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_MEASURE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_MEASURE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_MEASURE,.fsmagic = DEVPTS_SUPER_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_MEASURE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = MEASURE,.func = MMAP_CHECK,.mask = MAY_EXEC,
+       {.action = DONT_MEASURE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_MEASURE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_MEASURE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_MEASURE, .fsmagic = TMPFS_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_MEASURE, .fsmagic = DEVPTS_SUPER_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_MEASURE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_MEASURE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
         .flags = IMA_FUNC | IMA_MASK},
-       {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
+       {.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
         .flags = IMA_FUNC | IMA_MASK},
-       {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = GLOBAL_ROOT_UID,
+       {.action = MEASURE, .func = FILE_CHECK, .mask = MAY_READ, .uid = GLOBAL_ROOT_UID,
         .flags = IMA_FUNC | IMA_MASK | IMA_UID},
-       {.action = MEASURE,.func = MODULE_CHECK, .flags = IMA_FUNC},
+       {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC},
 };
 
 static struct ima_rule_entry default_appraise_rules[] = {
-       {.action = DONT_APPRAISE,.fsmagic = PROC_SUPER_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_APPRAISE,.fsmagic = SYSFS_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_APPRAISE,.fsmagic = DEBUGFS_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_APPRAISE,.fsmagic = TMPFS_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_APPRAISE,.fsmagic = RAMFS_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_APPRAISE,.fsmagic = DEVPTS_SUPER_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_APPRAISE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_APPRAISE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_APPRAISE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = DONT_APPRAISE,.fsmagic = CGROUP_SUPER_MAGIC,.flags = IMA_FSMAGIC},
-       {.action = APPRAISE,.fowner = GLOBAL_ROOT_UID,.flags = IMA_FOWNER},
+       {.action = DONT_APPRAISE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE, .fsmagic = TMPFS_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE, .fsmagic = RAMFS_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE, .fsmagic = DEVPTS_SUPER_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
+       {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
 };
 
 static LIST_HEAD(ima_default_rules);
@@ -122,12 +122,12 @@ static int __init default_appraise_policy_setup(char *str)
 }
 __setup("ima_appraise_tcb", default_appraise_policy_setup);
 
-/* 
+/*
  * Although the IMA policy does not change, the LSM policy can be
  * reloaded, leaving the IMA LSM based rules referring to the old,
  * stale LSM policy.
  *
- * Update the IMA LSM based rules to reflect the reloaded LSM policy. 
+ * Update the IMA LSM based rules to reflect the reloaded LSM policy.
  * We assume the rules still exist; and BUG_ON() if they don't.
  */
 static void ima_lsm_update_rules(void)
@@ -167,9 +167,11 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
        const struct cred *cred = current_cred();
        int i;
 
-       if ((rule->flags & IMA_FUNC) && rule->func != func)
+       if ((rule->flags & IMA_FUNC) &&
+           (rule->func != func && func != POST_SETATTR))
                return false;
-       if ((rule->flags & IMA_MASK) && rule->mask != mask)
+       if ((rule->flags & IMA_MASK) &&
+           (rule->mask != mask && func != POST_SETATTR))
                return false;
        if ((rule->flags & IMA_FSMAGIC)
            && rule->fsmagic != inode->i_sb->s_magic)
@@ -216,7 +218,7 @@ retry:
                        retried = 1;
                        ima_lsm_update_rules();
                        goto retry;
-               } 
+               }
                if (!rc)
                        return false;
        }
@@ -232,7 +234,7 @@ static int get_subaction(struct ima_rule_entry *rule, int func)
        if (!(rule->flags & IMA_FUNC))
                return IMA_FILE_APPRAISE;
 
-       switch(func) {
+       switch (func) {
        case MMAP_CHECK:
                return IMA_MMAP_APPRAISE;
        case BPRM_CHECK:
@@ -304,7 +306,7 @@ void __init ima_init_policy(void)
        measure_entries = ima_use_tcb ? ARRAY_SIZE(default_rules) : 0;
        appraise_entries = ima_use_appraise_tcb ?
                         ARRAY_SIZE(default_appraise_rules) : 0;
-       
+
        for (i = 0; i < measure_entries + appraise_entries; i++) {
                if (i < measure_entries)
                        list_add_tail(&default_rules[i].list,
@@ -329,7 +331,7 @@ void __init ima_init_policy(void)
  */
 void ima_update_policy(void)
 {
-       const char *op = "policy_update";
+       static const char op[] = "policy_update";
        const char *cause = "already exists";
        int result = 1;
        int audit_info = 0;
@@ -520,8 +522,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
                                break;
                        }
 
-                       result = strict_strtoul(args[0].from, 16,
-                                               &entry->fsmagic);
+                       result = kstrtoul(args[0].from, 16, &entry->fsmagic);
                        if (!result)
                                entry->flags |= IMA_FSMAGIC;
                        break;
@@ -547,7 +548,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
                                break;
                        }
 
-                       result = strict_strtoul(args[0].from, 10, &lnum);
+                       result = kstrtoul(args[0].from, 10, &lnum);
                        if (!result) {
                                entry->uid = make_kuid(current_user_ns(), (uid_t)lnum);
                                if (!uid_valid(entry->uid) || (((uid_t)lnum) != lnum))
@@ -564,7 +565,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
                                break;
                        }
 
-                       result = strict_strtoul(args[0].from, 10, &lnum);
+                       result = kstrtoul(args[0].from, 10, &lnum);
                        if (!result) {
                                entry->fowner = make_kuid(current_user_ns(), (uid_t)lnum);
                                if (!uid_valid(entry->fowner) || (((uid_t)lnum) != lnum))
@@ -645,7 +646,7 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
  */
 ssize_t ima_parse_add_rule(char *rule)
 {
-       const char *op = "update_policy";
+       static const char op[] = "update_policy";
        char *p;
        struct ima_rule_entry *entry;
        ssize_t result, len;
index d85e99761f4fc66afa251bb2bd657062d84d9b77..552705d5a78d0bbd518cb416e146846cf23df7e4 100644 (file)
@@ -18,6 +18,9 @@
  *       The measurement list is append-only. No entry is
  *       ever removed or changed during the boot-cycle.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/rculist.h>
 #include <linux/slab.h>
@@ -72,7 +75,7 @@ static int ima_add_digest_entry(struct ima_template_entry *entry)
 
        qe = kmalloc(sizeof(*qe), GFP_KERNEL);
        if (qe == NULL) {
-               pr_err("IMA: OUT OF MEMORY ERROR creating queue entry.\n");
+               pr_err("OUT OF MEMORY ERROR creating queue entry\n");
                return -ENOMEM;
        }
        qe->entry = entry;
@@ -95,8 +98,7 @@ static int ima_pcr_extend(const u8 *hash)
 
        result = tpm_pcr_extend(TPM_ANY_NUM, CONFIG_IMA_MEASURE_PCR_IDX, hash);
        if (result != 0)
-               pr_err("IMA: Error Communicating to TPM chip, result: %d\n",
-                      result);
+               pr_err("Error Communicating to TPM chip, result: %d\n", result);
        return result;
 }
 
@@ -115,7 +117,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
 
        mutex_lock(&ima_extend_list_mutex);
        if (!violation) {
-               memcpy(digest, entry->digest, sizeof digest);
+               memcpy(digest, entry->digest, sizeof(digest));
                if (ima_lookup_digest_entry(digest)) {
                        audit_cause = "hash_exists";
                        result = -EEXIST;
@@ -131,7 +133,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation,
        }
 
        if (violation)          /* invalidate pcr */
-               memset(digest, 0xff, sizeof digest);
+               memset(digest, 0xff, sizeof(digest));
 
        tpmresult = ima_pcr_extend(digest);
        if (tpmresult != 0) {
index 635695f6a185a1d24ee3d1bfb05d4f7ebe8cedb0..a076a967ec4768f64ebfcd0a84509080e7eb6b18 100644 (file)
@@ -12,6 +12,9 @@
  * File: ima_template.c
  *      Helpers to manage template descriptors.
  */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <crypto/hash_info.h>
 
 #include "ima.h"
 
 static struct ima_template_desc defined_templates[] = {
        {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
-       {.name = "ima-ng",.fmt = "d-ng|n-ng"},
-       {.name = "ima-sig",.fmt = "d-ng|n-ng|sig"},
+       {.name = "ima-ng", .fmt = "d-ng|n-ng"},
+       {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
 };
 
 static struct ima_template_field supported_fields[] = {
-       {.field_id = "d",.field_init = ima_eventdigest_init,
+       {.field_id = "d", .field_init = ima_eventdigest_init,
         .field_show = ima_show_template_digest},
-       {.field_id = "n",.field_init = ima_eventname_init,
+       {.field_id = "n", .field_init = ima_eventname_init,
         .field_show = ima_show_template_string},
-       {.field_id = "d-ng",.field_init = ima_eventdigest_ng_init,
+       {.field_id = "d-ng", .field_init = ima_eventdigest_ng_init,
         .field_show = ima_show_template_digest_ng},
-       {.field_id = "n-ng",.field_init = ima_eventname_ng_init,
+       {.field_id = "n-ng", .field_init = ima_eventname_ng_init,
         .field_show = ima_show_template_string},
-       {.field_id = "sig",.field_init = ima_eventsig_init,
+       {.field_id = "sig", .field_init = ima_eventsig_init,
         .field_show = ima_show_template_sig},
 };
 
@@ -58,7 +61,7 @@ static int __init ima_template_setup(char *str)
         */
        if (template_len == 3 && strcmp(str, IMA_TEMPLATE_IMA_NAME) == 0 &&
            ima_hash_algo != HASH_ALGO_SHA1 && ima_hash_algo != HASH_ALGO_MD5) {
-               pr_err("IMA: template does not support hash alg\n");
+               pr_err("template does not support hash alg\n");
                return 1;
        }
 
index 1683bbf289a407048daad7d4c73154fdb05cfec6..1506f02485726e18e3f6ba5c8c057da9e00e296a 100644 (file)
@@ -27,7 +27,6 @@ static bool ima_template_hash_algo_allowed(u8 algo)
 enum data_formats {
        DATA_FMT_DIGEST = 0,
        DATA_FMT_DIGEST_WITH_ALGO,
-       DATA_FMT_EVENT_NAME,
        DATA_FMT_STRING,
        DATA_FMT_HEX
 };
@@ -37,18 +36,10 @@ static int ima_write_template_field_data(const void *data, const u32 datalen,
                                         struct ima_field_data *field_data)
 {
        u8 *buf, *buf_ptr;
-       u32 buflen;
+       u32 buflen = datalen;
 
-       switch (datafmt) {
-       case DATA_FMT_EVENT_NAME:
-               buflen = IMA_EVENT_NAME_LEN_MAX + 1;
-               break;
-       case DATA_FMT_STRING:
+       if (datafmt == DATA_FMT_STRING)
                buflen = datalen + 1;
-               break;
-       default:
-               buflen = datalen;
-       }
 
        buf = kzalloc(buflen, GFP_KERNEL);
        if (!buf)
@@ -63,7 +54,7 @@ static int ima_write_template_field_data(const void *data, const u32 datalen,
         * split into multiple template fields (the space is the delimitator
         * character for measurements lists in ASCII format).
         */
-       if (datafmt == DATA_FMT_EVENT_NAME || datafmt == DATA_FMT_STRING) {
+       if (datafmt == DATA_FMT_STRING) {
                for (buf_ptr = buf; buf_ptr - buf < datalen; buf_ptr++)
                        if (*buf_ptr == ' ')
                                *buf_ptr = '_';
@@ -109,13 +100,16 @@ static void ima_show_template_data_binary(struct seq_file *m,
                                          enum data_formats datafmt,
                                          struct ima_field_data *field_data)
 {
+       u32 len = (show == IMA_SHOW_BINARY_OLD_STRING_FMT) ?
+           strlen(field_data->data) : field_data->len;
+
        if (show != IMA_SHOW_BINARY_NO_FIELD_LEN)
-               ima_putc(m, &field_data->len, sizeof(u32));
+               ima_putc(m, &len, sizeof(len));
 
-       if (!field_data->len)
+       if (!len)
                return;
 
-       ima_putc(m, field_data->data, field_data->len);
+       ima_putc(m, field_data->data, len);
 }
 
 static void ima_show_template_field_data(struct seq_file *m,
@@ -129,6 +123,7 @@ static void ima_show_template_field_data(struct seq_file *m,
                break;
        case IMA_SHOW_BINARY:
        case IMA_SHOW_BINARY_NO_FIELD_LEN:
+       case IMA_SHOW_BINARY_OLD_STRING_FMT:
                ima_show_template_data_binary(m, show, datafmt, field_data);
                break;
        default:
@@ -277,8 +272,6 @@ static int ima_eventname_init_common(struct integrity_iint_cache *iint,
 {
        const char *cur_filename = NULL;
        u32 cur_filename_len = 0;
-       enum data_formats fmt = size_limit ?
-           DATA_FMT_EVENT_NAME : DATA_FMT_STRING;
 
        BUG_ON(filename == NULL && file == NULL);
 
@@ -301,7 +294,7 @@ static int ima_eventname_init_common(struct integrity_iint_cache *iint,
                cur_filename_len = IMA_EVENT_NAME_LEN_MAX;
 out:
        return ima_write_template_field_data(cur_filename, cur_filename_len,
-                                            fmt, field_data);
+                                            DATA_FMT_STRING, field_data);
 }
 
 /*
index d7efb30404aaed01d860a5bf274477ce56e2e481..aab9fa5a8231e7380097a96092296bdcebfa22f2 100644 (file)
@@ -7,7 +7,7 @@
  * the Free Software Foundation, version 2 of the License.
  *
  * File: integrity_audit.c
- *     Audit calls for the integrity subsystem
+ *     Audit calls for the integrity subsystem
  */
 
 #include <linux/fs.h>
@@ -22,7 +22,7 @@ static int __init integrity_audit_setup(char *str)
 {
        unsigned long audit;
 
-       if (!strict_strtoul(str, 0, &audit))
+       if (!kstrtoul(str, 0, &audit))
                integrity_audit_info = audit ? 1 : 0;
        return 1;
 }
@@ -33,6 +33,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
                         const char *cause, int result, int audit_info)
 {
        struct audit_buffer *ab;
+       char name[TASK_COMM_LEN];
 
        if (!integrity_audit_info && audit_info == 1)   /* Skip info messages */
                return;
@@ -49,7 +50,7 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
        audit_log_format(ab, " cause=");
        audit_log_string(ab, cause);
        audit_log_format(ab, " comm=");
-       audit_log_untrustedstring(ab, current->comm);
+       audit_log_untrustedstring(ab, get_task_comm(name, current));
        if (fname) {
                audit_log_format(ab, " name=");
                audit_log_untrustedstring(ab, fname);
index 9e1e005c75967d497831fb67146020aeed4bc4a8..5fe443d120afe81826902cc70efecff24ccee1bb 100644 (file)
@@ -609,7 +609,7 @@ static struct encrypted_key_payload *encrypted_key_alloc(struct key *key,
        long dlen;
        int ret;
 
-       ret = strict_strtol(datalen, 10, &dlen);
+       ret = kstrtol(datalen, 10, &dlen);
        if (ret < 0 || dlen < MIN_DATA_SIZE || dlen > MAX_DATA_SIZE)
                return ERR_PTR(-EINVAL);
 
index 80b2aac4f50ceda614d03c815f7638aa88a0c933..5f20da01fd8d317f835375de9654f42c1a1b4e8b 100644 (file)
@@ -176,20 +176,11 @@ extern int key_task_permission(const key_ref_t key_ref,
 /*
  * Check to see whether permission is granted to use a key in the desired way.
  */
-static inline int key_permission(const key_ref_t key_ref, key_perm_t perm)
+static inline int key_permission(const key_ref_t key_ref, unsigned perm)
 {
        return key_task_permission(key_ref, current_cred(), perm);
 }
 
-/* required permissions */
-#define        KEY_VIEW        0x01    /* require permission to view attributes */
-#define        KEY_READ        0x02    /* require permission to read content */
-#define        KEY_WRITE       0x04    /* require permission to update / modify */
-#define        KEY_SEARCH      0x08    /* require permission to search (keyring) or find (key) */
-#define        KEY_LINK        0x10    /* require permission to link */
-#define        KEY_SETATTR     0x20    /* require permission to change attributes */
-#define        KEY_ALL         0x3f    /* all the above permissions */
-
 /*
  * Authorisation record for request_key().
  */
index 6e21c11e48bc1cd434664d28f83084b54db50bd6..2048a110e7f18f0bd1e78006a88dc7bc675c9994 100644 (file)
@@ -714,7 +714,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref,
        int ret;
 
        /* need write permission on the key to update it */
-       ret = key_permission(key_ref, KEY_WRITE);
+       ret = key_permission(key_ref, KEY_NEED_WRITE);
        if (ret < 0)
                goto error;
 
@@ -838,7 +838,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
 
        /* if we're going to allocate a new key, we're going to have
         * to modify the keyring */
-       ret = key_permission(keyring_ref, KEY_WRITE);
+       ret = key_permission(keyring_ref, KEY_NEED_WRITE);
        if (ret < 0) {
                key_ref = ERR_PTR(ret);
                goto error_link_end;
@@ -928,7 +928,7 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen)
        key_check(key);
 
        /* the key must be writable */
-       ret = key_permission(key_ref, KEY_WRITE);
+       ret = key_permission(key_ref, KEY_NEED_WRITE);
        if (ret < 0)
                goto error;
 
index cee72ce642221e816968cb81069407fe01edb138..cd5bd0cef25df3fce5801e938567e156d47f275f 100644 (file)
@@ -111,7 +111,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
        }
 
        /* find the target keyring (which must be writable) */
-       keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
+       keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE);
        if (IS_ERR(keyring_ref)) {
                ret = PTR_ERR(keyring_ref);
                goto error3;
@@ -195,7 +195,7 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type,
        dest_ref = NULL;
        if (destringid) {
                dest_ref = lookup_user_key(destringid, KEY_LOOKUP_CREATE,
-                                          KEY_WRITE);
+                                          KEY_NEED_WRITE);
                if (IS_ERR(dest_ref)) {
                        ret = PTR_ERR(dest_ref);
                        goto error3;
@@ -253,7 +253,7 @@ long keyctl_get_keyring_ID(key_serial_t id, int create)
        long ret;
 
        lflags = create ? KEY_LOOKUP_CREATE : 0;
-       key_ref = lookup_user_key(id, lflags, KEY_SEARCH);
+       key_ref = lookup_user_key(id, lflags, KEY_NEED_SEARCH);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error;
@@ -334,7 +334,7 @@ long keyctl_update_key(key_serial_t id,
        }
 
        /* find the target key (which must be writable) */
-       key_ref = lookup_user_key(id, 0, KEY_WRITE);
+       key_ref = lookup_user_key(id, 0, KEY_NEED_WRITE);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error2;
@@ -365,12 +365,12 @@ long keyctl_revoke_key(key_serial_t id)
        key_ref_t key_ref;
        long ret;
 
-       key_ref = lookup_user_key(id, 0, KEY_WRITE);
+       key_ref = lookup_user_key(id, 0, KEY_NEED_WRITE);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                if (ret != -EACCES)
                        goto error;
-               key_ref = lookup_user_key(id, 0, KEY_SETATTR);
+               key_ref = lookup_user_key(id, 0, KEY_NEED_SETATTR);
                if (IS_ERR(key_ref)) {
                        ret = PTR_ERR(key_ref);
                        goto error;
@@ -401,7 +401,7 @@ long keyctl_invalidate_key(key_serial_t id)
 
        kenter("%d", id);
 
-       key_ref = lookup_user_key(id, 0, KEY_SEARCH);
+       key_ref = lookup_user_key(id, 0, KEY_NEED_SEARCH);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error;
@@ -428,7 +428,7 @@ long keyctl_keyring_clear(key_serial_t ringid)
        key_ref_t keyring_ref;
        long ret;
 
-       keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
+       keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE);
        if (IS_ERR(keyring_ref)) {
                ret = PTR_ERR(keyring_ref);
 
@@ -470,13 +470,13 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid)
        key_ref_t keyring_ref, key_ref;
        long ret;
 
-       keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
+       keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE);
        if (IS_ERR(keyring_ref)) {
                ret = PTR_ERR(keyring_ref);
                goto error;
        }
 
-       key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE, KEY_LINK);
+       key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE, KEY_NEED_LINK);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error2;
@@ -505,7 +505,7 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
        key_ref_t keyring_ref, key_ref;
        long ret;
 
-       keyring_ref = lookup_user_key(ringid, 0, KEY_WRITE);
+       keyring_ref = lookup_user_key(ringid, 0, KEY_NEED_WRITE);
        if (IS_ERR(keyring_ref)) {
                ret = PTR_ERR(keyring_ref);
                goto error;
@@ -548,7 +548,7 @@ long keyctl_describe_key(key_serial_t keyid,
        char *tmpbuf;
        long ret;
 
-       key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_VIEW);
+       key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_NEED_VIEW);
        if (IS_ERR(key_ref)) {
                /* viewing a key under construction is permitted if we have the
                 * authorisation token handy */
@@ -639,7 +639,7 @@ long keyctl_keyring_search(key_serial_t ringid,
        }
 
        /* get the keyring at which to begin the search */
-       keyring_ref = lookup_user_key(ringid, 0, KEY_SEARCH);
+       keyring_ref = lookup_user_key(ringid, 0, KEY_NEED_SEARCH);
        if (IS_ERR(keyring_ref)) {
                ret = PTR_ERR(keyring_ref);
                goto error2;
@@ -649,7 +649,7 @@ long keyctl_keyring_search(key_serial_t ringid,
        dest_ref = NULL;
        if (destringid) {
                dest_ref = lookup_user_key(destringid, KEY_LOOKUP_CREATE,
-                                          KEY_WRITE);
+                                          KEY_NEED_WRITE);
                if (IS_ERR(dest_ref)) {
                        ret = PTR_ERR(dest_ref);
                        goto error3;
@@ -676,7 +676,7 @@ long keyctl_keyring_search(key_serial_t ringid,
 
        /* link the resulting key to the destination keyring if we can */
        if (dest_ref) {
-               ret = key_permission(key_ref, KEY_LINK);
+               ret = key_permission(key_ref, KEY_NEED_LINK);
                if (ret < 0)
                        goto error6;
 
@@ -727,7 +727,7 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
        key = key_ref_to_ptr(key_ref);
 
        /* see if we can read it directly */
-       ret = key_permission(key_ref, KEY_READ);
+       ret = key_permission(key_ref, KEY_NEED_READ);
        if (ret == 0)
                goto can_read_key;
        if (ret != -EACCES)
@@ -799,7 +799,7 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
                goto error;
 
        key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
-                                 KEY_SETATTR);
+                                 KEY_NEED_SETATTR);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error;
@@ -905,7 +905,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
                goto error;
 
        key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
-                                 KEY_SETATTR);
+                                 KEY_NEED_SETATTR);
        if (IS_ERR(key_ref)) {
                ret = PTR_ERR(key_ref);
                goto error;
@@ -947,7 +947,7 @@ static long get_instantiation_keyring(key_serial_t ringid,
 
        /* if a specific keyring is nominated by ID, then use that */
        if (ringid > 0) {
-               dkref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
+               dkref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE);
                if (IS_ERR(dkref))
                        return PTR_ERR(dkref);
                *_dest_keyring = key_ref_to_ptr(dkref);
@@ -1315,7 +1315,7 @@ long keyctl_set_timeout(key_serial_t id, unsigned timeout)
        long ret;
 
        key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
-                                 KEY_SETATTR);
+                                 KEY_NEED_SETATTR);
        if (IS_ERR(key_ref)) {
                /* setting the timeout on a key under construction is permitted
                 * if we have the authorisation token handy */
@@ -1418,7 +1418,7 @@ long keyctl_get_security(key_serial_t keyid,
        char *context;
        long ret;
 
-       key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_VIEW);
+       key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, KEY_NEED_VIEW);
        if (IS_ERR(key_ref)) {
                if (PTR_ERR(key_ref) != -EACCES)
                        return PTR_ERR(key_ref);
@@ -1482,7 +1482,7 @@ long keyctl_session_to_parent(void)
        struct cred *cred;
        int ret;
 
-       keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_LINK);
+       keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_NEED_LINK);
        if (IS_ERR(keyring_r))
                return PTR_ERR(keyring_r);
 
index 2fb2576dc6448b3c1020dc311e0d81bfe77fb768..9cf2575f0d97c8b237928f1e1ab46b4ad3895653 100644 (file)
@@ -541,7 +541,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data)
        /* key must have search permissions */
        if (!(ctx->flags & KEYRING_SEARCH_NO_CHECK_PERM) &&
            key_task_permission(make_key_ref(key, ctx->possessed),
-                               ctx->cred, KEY_SEARCH) < 0) {
+                               ctx->cred, KEY_NEED_SEARCH) < 0) {
                ctx->result = ERR_PTR(-EACCES);
                kleave(" = %d [!perm]", ctx->skipped_ret);
                goto skipped;
@@ -721,7 +721,7 @@ ascend_to_node:
                /* Search a nested keyring */
                if (!(ctx->flags & KEYRING_SEARCH_NO_CHECK_PERM) &&
                    key_task_permission(make_key_ref(key, ctx->possessed),
-                                       ctx->cred, KEY_SEARCH) < 0)
+                                       ctx->cred, KEY_NEED_SEARCH) < 0)
                        continue;
 
                /* stack the current position */
@@ -843,7 +843,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
                return ERR_PTR(-ENOTDIR);
 
        if (!(ctx->flags & KEYRING_SEARCH_NO_CHECK_PERM)) {
-               err = key_task_permission(keyring_ref, ctx->cred, KEY_SEARCH);
+               err = key_task_permission(keyring_ref, ctx->cred, KEY_NEED_SEARCH);
                if (err < 0)
                        return ERR_PTR(err);
        }
@@ -973,7 +973,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check)
 
                        if (!skip_perm_check &&
                            key_permission(make_key_ref(keyring, 0),
-                                          KEY_SEARCH) < 0)
+                                          KEY_NEED_SEARCH) < 0)
                                continue;
 
                        /* we've got a match but we might end up racing with
index efcc0c855a0db1284ee3debcb9be64823d9be3ed..732cc0beffdfc74b74eddbf173ee30bd9d0455db 100644 (file)
@@ -28,7 +28,7 @@
  * permissions bits or the LSM check.
  */
 int key_task_permission(const key_ref_t key_ref, const struct cred *cred,
-                       key_perm_t perm)
+                       unsigned perm)
 {
        struct key *key;
        key_perm_t kperm;
@@ -68,7 +68,7 @@ use_these_perms:
        if (is_key_possessed(key_ref))
                kperm |= key->perm >> 24;
 
-       kperm = kperm & perm & KEY_ALL;
+       kperm = kperm & perm & KEY_NEED_ALL;
 
        if (kperm != perm)
                return -EACCES;
index 0ad3ee2837812344d9cf20153c6df49f4dff168e..c9fae5ea89fe68b2dcaeed5a30acc9f47c54c6ad 100644 (file)
@@ -108,7 +108,7 @@ static long key_get_persistent(struct user_namespace *ns, kuid_t uid,
        return PTR_ERR(persistent_ref);
 
 found:
-       ret = key_task_permission(persistent_ref, current_cred(), KEY_LINK);
+       ret = key_task_permission(persistent_ref, current_cred(), KEY_NEED_LINK);
        if (ret == 0) {
                persistent = key_ref_to_ptr(persistent_ref);
                ret = key_link(key_ref_to_ptr(dest_ref), persistent);
@@ -151,7 +151,7 @@ long keyctl_get_persistent(uid_t _uid, key_serial_t destid)
        }
 
        /* There must be a destination keyring */
-       dest_ref = lookup_user_key(destid, KEY_LOOKUP_CREATE, KEY_WRITE);
+       dest_ref = lookup_user_key(destid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE);
        if (IS_ERR(dest_ref))
                return PTR_ERR(dest_ref);
        if (key_ref_to_ptr(dest_ref)->type != &key_type_keyring) {
index 88e9a466940f642af60f61b407888155ba057be5..d3f6f2fd21db84bc197ed82b14808b6bc9bc4e87 100644 (file)
@@ -218,7 +218,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
         * - the caller holds a spinlock, and thus the RCU read lock, making our
         *   access to __current_cred() safe
         */
-       rc = key_task_permission(key_ref, ctx.cred, KEY_VIEW);
+       rc = key_task_permission(key_ref, ctx.cred, KEY_NEED_VIEW);
        if (rc < 0)
                return 0;
 
index 8c0af08760c809b2923d04c5cc3b114c75e27b27..b68faa1a5cfdf2a97a65b73bfb2a8a33916db3f0 100644 (file)
@@ -15,7 +15,7 @@
 
 static const int zero, one = 1, max = INT_MAX;
 
-ctl_table key_sysctls[] = {
+struct ctl_table key_sysctls[] = {
        {
                .procname = "maxkeys",
                .data = &key_quota_maxkeys,
index e13fcf7636f7ffa0ff40d7cd60408645621dab1f..6b804aa4529a171bfab534307903b142c23cf891 100644 (file)
@@ -753,7 +753,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
                                return -EINVAL;
                        break;
                case Opt_keyhandle:
-                       res = strict_strtoul(args[0].from, 16, &handle);
+                       res = kstrtoul(args[0].from, 16, &handle);
                        if (res < 0)
                                return -EINVAL;
                        opt->keytype = SEAL_keytype;
@@ -782,7 +782,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
                                return -EINVAL;
                        break;
                case Opt_pcrlock:
-                       res = strict_strtoul(args[0].from, 10, &lock);
+                       res = kstrtoul(args[0].from, 10, &lock);
                        if (res < 0)
                                return -EINVAL;
                        opt->pcrlock = lock;
@@ -820,7 +820,7 @@ static int datablob_parse(char *datablob, struct trusted_key_payload *p,
                c = strsep(&datablob, " \t");
                if (!c)
                        return -EINVAL;
-               ret = strict_strtol(c, 10, &keylen);
+               ret = kstrtol(c, 10, &keylen);
                if (ret < 0 || keylen < MIN_KEY_SIZE || keylen > MAX_KEY_SIZE)
                        return -EINVAL;
                p->key_len = keylen;
index 919cad93ac82fa2fa7c017b5c85353ca8ac6818e..d91fec458e905053872cd9737b819ea142de9989 100644 (file)
@@ -1407,7 +1407,7 @@ void security_key_free(struct key *key)
 }
 
 int security_key_permission(key_ref_t key_ref,
-                           const struct cred *cred, key_perm_t perm)
+                           const struct cred *cred, unsigned perm)
 {
        return security_ops->key_permission(key_ref, cred, perm);
 }
index b03b0776955a2c703c4ed95c3496eca5da15b00c..d4cbf7d16f075e43b6675828903baee5d2088dde 100644 (file)
@@ -106,7 +106,7 @@ int selinux_enforcing;
 static int __init enforcing_setup(char *str)
 {
        unsigned long enforcing;
-       if (!strict_strtoul(str, 0, &enforcing))
+       if (!kstrtoul(str, 0, &enforcing))
                selinux_enforcing = enforcing ? 1 : 0;
        return 1;
 }
@@ -119,7 +119,7 @@ int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
 static int __init selinux_enabled_setup(char *str)
 {
        unsigned long enabled;
-       if (!strict_strtoul(str, 0, &enabled))
+       if (!kstrtoul(str, 0, &enabled))
                selinux_enabled = enabled ? 1 : 0;
        return 1;
 }
@@ -5722,7 +5722,7 @@ static void selinux_key_free(struct key *k)
 
 static int selinux_key_permission(key_ref_t key_ref,
                                  const struct cred *cred,
-                                 key_perm_t perm)
+                                 unsigned perm)
 {
        struct key *key;
        struct key_security_struct *ksec;
index d60c0ee66387d8078055414992ad36d7a2d31fa8..c71737f6d1cc6284edaf1b7b0f8db43abfebd54d 100644 (file)
@@ -54,7 +54,7 @@ unsigned int selinux_checkreqprot = CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE;
 static int __init checkreqprot_setup(char *str)
 {
        unsigned long checkreqprot;
-       if (!strict_strtoul(str, 0, &checkreqprot))
+       if (!kstrtoul(str, 0, &checkreqprot))
                selinux_checkreqprot = checkreqprot ? 1 : 0;
        return 1;
 }
index d072fd32212d36cb359dbd31006614c3471f2981..020307ef097296f2eac85be8ae823fdad93ff508 100644 (file)
@@ -80,8 +80,8 @@ struct superblock_smack {
 
 struct socket_smack {
        struct smack_known      *smk_out;       /* outbound label */
-       char                    *smk_in;        /* inbound label */
-       char                    *smk_packet;    /* TCP peer label */
+       struct smack_known      *smk_in;        /* inbound label */
+       struct smack_known      *smk_packet;    /* TCP peer label */
 };
 
 /*
@@ -133,7 +133,7 @@ struct smk_port_label {
        struct list_head        list;
        struct sock             *smk_sock;      /* socket initialized on */
        unsigned short          smk_port;       /* the port number */
-       char                    *smk_in;        /* incoming label */
+       struct smack_known      *smk_in;        /* inbound label */
        struct smack_known      *smk_out;       /* outgoing label */
 };
 
@@ -176,6 +176,14 @@ struct smk_port_label {
  */
 #define SMACK_CIPSO_MAXCATNUM           184     /* 23 * 8 */
 
+/*
+ * Ptrace rules
+ */
+#define SMACK_PTRACE_DEFAULT   0
+#define SMACK_PTRACE_EXACT     1
+#define SMACK_PTRACE_DRACONIAN 2
+#define SMACK_PTRACE_MAX       SMACK_PTRACE_DRACONIAN
+
 /*
  * Flags for untraditional access modes.
  * It shouldn't be necessary to avoid conflicts with definitions
@@ -225,6 +233,7 @@ struct inode_smack *new_inode_smack(char *);
  */
 int smk_access_entry(char *, char *, struct list_head *);
 int smk_access(struct smack_known *, char *, int, struct smk_audit_info *);
+int smk_tskacc(struct task_smack *, char *, u32, struct smk_audit_info *);
 int smk_curacc(char *, u32, struct smk_audit_info *);
 struct smack_known *smack_from_secid(const u32);
 char *smk_parse_smack(const char *string, int len);
@@ -244,6 +253,7 @@ extern struct smack_known *smack_net_ambient;
 extern struct smack_known *smack_onlycap;
 extern struct smack_known *smack_syslog_label;
 extern const char *smack_cipso_option;
+extern int smack_ptrace_rule;
 
 extern struct smack_known smack_known_floor;
 extern struct smack_known smack_known_hat;
index 14293cd9b1e53b4a260e9258a5cad54c75d71204..c062e9467b62f91cb2b975f271de60755d66248c 100644 (file)
@@ -192,20 +192,21 @@ out_audit:
 }
 
 /**
- * smk_curacc - determine if current has a specific access to an object
+ * smk_tskacc - determine if a task has a specific access to an object
+ * @tsp: a pointer to the subject task
  * @obj_label: a pointer to the object's Smack label
  * @mode: the access requested, in "MAY" format
  * @a : common audit data
  *
- * This function checks the current subject label/object label pair
+ * This function checks the subject task's label/object label pair
  * in the access rule list and returns 0 if the access is permitted,
- * non zero otherwise. It allows that current may have the capability
+ * non zero otherwise. It allows that the task may have the capability
  * to override the rules.
  */
-int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
+int smk_tskacc(struct task_smack *subject, char *obj_label,
+              u32 mode, struct smk_audit_info *a)
 {
-       struct task_smack *tsp = current_security();
-       struct smack_known *skp = smk_of_task(tsp);
+       struct smack_known *skp = smk_of_task(subject);
        int may;
        int rc;
 
@@ -219,7 +220,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
                 * it can further restrict access.
                 */
                may = smk_access_entry(skp->smk_known, obj_label,
-                                       &tsp->smk_rules);
+                                       &subject->smk_rules);
                if (may < 0)
                        goto out_audit;
                if ((mode & may) == mode)
@@ -241,6 +242,24 @@ out_audit:
        return rc;
 }
 
+/**
+ * smk_curacc - determine if current has a specific access to an object
+ * @obj_label: a pointer to the object's Smack label
+ * @mode: the access requested, in "MAY" format
+ * @a : common audit data
+ *
+ * This function checks the current subject label/object label pair
+ * in the access rule list and returns 0 if the access is permitted,
+ * non zero otherwise. It allows that current may have the capability
+ * to override the rules.
+ */
+int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
+{
+       struct task_smack *tsp = current_security();
+
+       return smk_tskacc(tsp, obj_label, mode, a);
+}
+
 #ifdef CONFIG_AUDIT
 /**
  * smack_str_from_perm : helper to transalate an int to a
@@ -285,7 +304,10 @@ static void smack_log_callback(struct audit_buffer *ab, void *a)
        audit_log_untrustedstring(ab, sad->subject);
        audit_log_format(ab, " object=");
        audit_log_untrustedstring(ab, sad->object);
-       audit_log_format(ab, " requested=%s", sad->request);
+       if (sad->request[0] == '\0')
+               audit_log_format(ab, " labels_differ");
+       else
+               audit_log_format(ab, " requested=%s", sad->request);
 }
 
 /**
index 14f52be78c75e279f2bad288c66513a016a1ec3c..f2c30801ce413224bade6b1ba3f34fb676fd2e80 100644 (file)
@@ -157,6 +157,74 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
        return rc;
 }
 
+/**
+ * smk_ptrace_mode - helper function for converting PTRACE_MODE_* into MAY_*
+ * @mode - input mode in form of PTRACE_MODE_*
+ *
+ * Returns a converted MAY_* mode usable by smack rules
+ */
+static inline unsigned int smk_ptrace_mode(unsigned int mode)
+{
+       switch (mode) {
+       case PTRACE_MODE_READ:
+               return MAY_READ;
+       case PTRACE_MODE_ATTACH:
+               return MAY_READWRITE;
+       }
+
+       return 0;
+}
+
+/**
+ * smk_ptrace_rule_check - helper for ptrace access
+ * @tracer: tracer process
+ * @tracee_label: label of the process that's about to be traced,
+ *                the pointer must originate from smack structures
+ * @mode: ptrace attachment mode (PTRACE_MODE_*)
+ * @func: name of the function that called us, used for audit
+ *
+ * Returns 0 on access granted, -error on error
+ */
+static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label,
+                                unsigned int mode, const char *func)
+{
+       int rc;
+       struct smk_audit_info ad, *saip = NULL;
+       struct task_smack *tsp;
+       struct smack_known *skp;
+
+       if ((mode & PTRACE_MODE_NOAUDIT) == 0) {
+               smk_ad_init(&ad, func, LSM_AUDIT_DATA_TASK);
+               smk_ad_setfield_u_tsk(&ad, tracer);
+               saip = &ad;
+       }
+
+       tsp = task_security(tracer);
+       skp = smk_of_task(tsp);
+
+       if ((mode & PTRACE_MODE_ATTACH) &&
+           (smack_ptrace_rule == SMACK_PTRACE_EXACT ||
+            smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)) {
+               if (skp->smk_known == tracee_label)
+                       rc = 0;
+               else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)
+                       rc = -EACCES;
+               else if (capable(CAP_SYS_PTRACE))
+                       rc = 0;
+               else
+                       rc = -EACCES;
+
+               if (saip)
+                       smack_log(skp->smk_known, tracee_label, 0, rc, saip);
+
+               return rc;
+       }
+
+       /* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */
+       rc = smk_tskacc(tsp, tracee_label, smk_ptrace_mode(mode), saip);
+       return rc;
+}
+
 /*
  * LSM hooks.
  * We he, that is fun!
@@ -165,16 +233,15 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
 /**
  * smack_ptrace_access_check - Smack approval on PTRACE_ATTACH
  * @ctp: child task pointer
- * @mode: ptrace attachment mode
+ * @mode: ptrace attachment mode (PTRACE_MODE_*)
  *
  * Returns 0 if access is OK, an error code otherwise
  *
- * Do the capability checks, and require read and write.
+ * Do the capability checks.
  */
 static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
 {
        int rc;
-       struct smk_audit_info ad;
        struct smack_known *skp;
 
        rc = cap_ptrace_access_check(ctp, mode);
@@ -182,10 +249,8 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
                return rc;
 
        skp = smk_of_task(task_security(ctp));
-       smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
-       smk_ad_setfield_u_tsk(&ad, ctp);
 
-       rc = smk_curacc(skp->smk_known, mode, &ad);
+       rc = smk_ptrace_rule_check(current, skp->smk_known, mode, __func__);
        return rc;
 }
 
@@ -195,23 +260,21 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
  *
  * Returns 0 if access is OK, an error code otherwise
  *
- * Do the capability checks, and require read and write.
+ * Do the capability checks, and require PTRACE_MODE_ATTACH.
  */
 static int smack_ptrace_traceme(struct task_struct *ptp)
 {
        int rc;
-       struct smk_audit_info ad;
        struct smack_known *skp;
 
        rc = cap_ptrace_traceme(ptp);
        if (rc != 0)
                return rc;
 
-       skp = smk_of_task(task_security(ptp));
-       smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
-       smk_ad_setfield_u_tsk(&ad, ptp);
+       skp = smk_of_task(current_security());
 
-       rc = smk_curacc(skp->smk_known, MAY_READWRITE, &ad);
+       rc = smk_ptrace_rule_check(ptp, skp->smk_known,
+                                  PTRACE_MODE_ATTACH, __func__);
        return rc;
 }
 
@@ -413,9 +476,11 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data)
         * Initialize the root inode.
         */
        isp = inode->i_security;
-       if (inode->i_security == NULL) {
-               inode->i_security = new_inode_smack(sp->smk_root);
-               isp = inode->i_security;
+       if (isp == NULL) {
+               isp = new_inode_smack(sp->smk_root);
+               if (isp == NULL)
+                       return -ENOMEM;
+               inode->i_security = isp;
        } else
                isp->smk_inode = sp->smk_root;
 
@@ -453,7 +518,7 @@ static int smack_sb_statfs(struct dentry *dentry)
  * smack_bprm_set_creds - set creds for exec
  * @bprm: the exec information
  *
- * Returns 0 if it gets a blob, -ENOMEM otherwise
+ * Returns 0 if it gets a blob, -EPERM if exec forbidden and -ENOMEM otherwise
  */
 static int smack_bprm_set_creds(struct linux_binprm *bprm)
 {
@@ -473,7 +538,22 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
        if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task)
                return 0;
 
-       if (bprm->unsafe)
+       if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
+               struct task_struct *tracer;
+               rc = 0;
+
+               rcu_read_lock();
+               tracer = ptrace_parent(current);
+               if (likely(tracer != NULL))
+                       rc = smk_ptrace_rule_check(tracer,
+                                                  isp->smk_task->smk_known,
+                                                  PTRACE_MODE_ATTACH,
+                                                  __func__);
+               rcu_read_unlock();
+
+               if (rc != 0)
+                       return rc;
+       } else if (bprm->unsafe)
                return -EPERM;
 
        bsp->smk_task = isp->smk_task;
@@ -880,18 +960,20 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
                return;
        }
 
-       skp = smk_import_entry(value, size);
        if (strcmp(name, XATTR_NAME_SMACK) == 0) {
+               skp = smk_import_entry(value, size);
                if (skp != NULL)
                        isp->smk_inode = skp->smk_known;
                else
                        isp->smk_inode = smack_known_invalid.smk_known;
        } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) {
+               skp = smk_import_entry(value, size);
                if (skp != NULL)
                        isp->smk_task = skp;
                else
                        isp->smk_task = &smack_known_invalid;
        } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
+               skp = smk_import_entry(value, size);
                if (skp != NULL)
                        isp->smk_mmap = skp;
                else
@@ -938,24 +1020,37 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
            strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
            strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
            strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 ||
-           strcmp(name, XATTR_NAME_SMACKMMAP)) {
+           strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
                if (!smack_privileged(CAP_MAC_ADMIN))
                        rc = -EPERM;
        } else
                rc = cap_inode_removexattr(dentry, name);
 
+       if (rc != 0)
+               return rc;
+
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
        smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
-       if (rc == 0)
-               rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
 
-       if (rc == 0) {
-               isp = dentry->d_inode->i_security;
+       rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad);
+       if (rc != 0)
+               return rc;
+
+       isp = dentry->d_inode->i_security;
+       /*
+        * Don't do anything special for these.
+        *      XATTR_NAME_SMACKIPIN
+        *      XATTR_NAME_SMACKIPOUT
+        *      XATTR_NAME_SMACKEXEC
+        */
+       if (strcmp(name, XATTR_NAME_SMACK) == 0)
                isp->smk_task = NULL;
+       else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0)
                isp->smk_mmap = NULL;
-       }
+       else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0)
+               isp->smk_flags &= ~SMK_INODE_TRANSMUTE;
 
-       return rc;
+       return 0;
 }
 
 /**
@@ -1000,7 +1095,7 @@ static int smack_inode_getsecurity(const struct inode *inode,
        ssp = sock->sk->sk_security;
 
        if (strcmp(name, XATTR_SMACK_IPIN) == 0)
-               isp = ssp->smk_in;
+               isp = ssp->smk_in->smk_known;
        else if (strcmp(name, XATTR_SMACK_IPOUT) == 0)
                isp = ssp->smk_out->smk_known;
        else
@@ -1367,19 +1462,32 @@ static int smack_file_receive(struct file *file)
 /**
  * smack_file_open - Smack dentry open processing
  * @file: the object
- * @cred: unused
+ * @cred: task credential
  *
  * Set the security blob in the file structure.
+ * Allow the open only if the task has read access. There are
+ * many read operations (e.g. fstat) that you can do with an
+ * fd even if you have the file open write-only.
  *
  * Returns 0
  */
 static int smack_file_open(struct file *file, const struct cred *cred)
 {
+       struct task_smack *tsp = cred->security;
        struct inode_smack *isp = file_inode(file)->i_security;
+       struct smk_audit_info ad;
+       int rc;
 
-       file->f_security = isp->smk_inode;
+       if (smack_privileged(CAP_MAC_OVERRIDE))
+               return 0;
 
-       return 0;
+       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);
+       if (rc == 0)
+               file->f_security = isp->smk_inode;
+
+       return rc;
 }
 
 /*
@@ -1764,7 +1872,7 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
        if (ssp == NULL)
                return -ENOMEM;
 
-       ssp->smk_in = skp->smk_known;
+       ssp->smk_in = skp;
        ssp->smk_out = skp;
        ssp->smk_packet = NULL;
 
@@ -2004,7 +2112,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
 
        if (act == SMK_RECEIVING) {
                skp = smack_net_ambient;
-               object = ssp->smk_in;
+               object = ssp->smk_in->smk_known;
        } else {
                skp = ssp->smk_out;
                object = smack_net_ambient->smk_known;
@@ -2034,9 +2142,9 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
        list_for_each_entry(spp, &smk_ipv6_port_list, list) {
                if (spp->smk_port != port)
                        continue;
-               object = spp->smk_in;
+               object = spp->smk_in->smk_known;
                if (act == SMK_CONNECTING)
-                       ssp->smk_packet = spp->smk_out->smk_known;
+                       ssp->smk_packet = spp->smk_out;
                break;
        }
 
@@ -2076,7 +2184,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
        int rc = 0;
 
        if (value == NULL || size > SMK_LONGLABEL || size == 0)
-               return -EACCES;
+               return -EINVAL;
 
        skp = smk_import_entry(value, size);
        if (skp == NULL)
@@ -2100,7 +2208,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
        ssp = sock->sk->sk_security;
 
        if (strcmp(name, XATTR_SMACK_IPIN) == 0)
-               ssp->smk_in = skp->smk_known;
+               ssp->smk_in = skp;
        else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) {
                ssp->smk_out = skp;
                if (sock->sk->sk_family == PF_INET) {
@@ -2713,6 +2821,15 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
         * of the superblock.
         */
        if (opt_dentry->d_parent == opt_dentry) {
+               if (sbp->s_magic == CGROUP_SUPER_MAGIC) {
+                       /*
+                        * The cgroup filesystem is never mounted,
+                        * so there's no opportunity to set the mount
+                        * options.
+                        */
+                       sbsp->smk_root = smack_known_star.smk_known;
+                       sbsp->smk_default = smack_known_star.smk_known;
+               }
                isp->smk_inode = sbsp->smk_root;
                isp->smk_flags |= SMK_INODE_INSTANT;
                goto unlockandout;
@@ -2726,16 +2843,20 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
         */
        switch (sbp->s_magic) {
        case SMACK_MAGIC:
+       case PIPEFS_MAGIC:
+       case SOCKFS_MAGIC:
+       case CGROUP_SUPER_MAGIC:
                /*
                 * Casey says that it's a little embarrassing
                 * that the smack file system doesn't do
                 * extended attributes.
-                */
-               final = smack_known_star.smk_known;
-               break;
-       case PIPEFS_MAGIC:
-               /*
+                *
                 * Casey says pipes are easy (?)
+                *
+                * Socket access is controlled by the socket
+                * structures associated with the task involved.
+                *
+                * Cgroupfs is special
                 */
                final = smack_known_star.smk_known;
                break;
@@ -2747,13 +2868,6 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
                 */
                final = ckp->smk_known;
                break;
-       case SOCKFS_MAGIC:
-               /*
-                * Socket access is controlled by the socket
-                * structures associated with the task involved.
-                */
-               final = smack_known_star.smk_known;
-               break;
        case PROC_SUPER_MAGIC:
                /*
                 * Casey says procfs appears not to care.
@@ -2959,30 +3073,34 @@ static int smack_unix_stream_connect(struct sock *sock,
                                     struct sock *other, struct sock *newsk)
 {
        struct smack_known *skp;
+       struct smack_known *okp;
        struct socket_smack *ssp = sock->sk_security;
        struct socket_smack *osp = other->sk_security;
        struct socket_smack *nsp = newsk->sk_security;
        struct smk_audit_info ad;
        int rc = 0;
-
 #ifdef CONFIG_AUDIT
        struct lsm_network_audit net;
-
-       smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
-       smk_ad_setfield_u_net_sk(&ad, other);
 #endif
 
        if (!smack_privileged(CAP_MAC_OVERRIDE)) {
                skp = ssp->smk_out;
-               rc = smk_access(skp, osp->smk_in, MAY_WRITE, &ad);
+               okp = osp->smk_out;
+#ifdef CONFIG_AUDIT
+               smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
+               smk_ad_setfield_u_net_sk(&ad, other);
+#endif
+               rc = smk_access(skp, okp->smk_known, MAY_WRITE, &ad);
+               if (rc == 0)
+                       rc = smk_access(okp, okp->smk_known, MAY_WRITE, NULL);
        }
 
        /*
         * Cross reference the peer labels for SO_PEERSEC.
         */
        if (rc == 0) {
-               nsp->smk_packet = ssp->smk_out->smk_known;
-               ssp->smk_packet = osp->smk_out->smk_known;
+               nsp->smk_packet = ssp->smk_out;
+               ssp->smk_packet = osp->smk_out;
        }
 
        return rc;
@@ -3014,7 +3132,7 @@ 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, MAY_WRITE, &ad);
+       return smk_access(skp, osp->smk_in->smk_known, MAY_WRITE, &ad);
 }
 
 /**
@@ -3109,7 +3227,7 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
                if (found)
                        return skp;
 
-               if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known)
+               if (ssp != NULL && ssp->smk_in == &smack_known_star)
                        return &smack_known_web;
                return &smack_known_star;
        }
@@ -3228,7 +3346,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
                 * This is the simplist possible security model
                 * for networking.
                 */
-               rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad);
+               rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad);
                if (rc != 0)
                        netlbl_skbuff_err(skb, rc, 0);
                break;
@@ -3263,7 +3381,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock,
 
        ssp = sock->sk->sk_security;
        if (ssp->smk_packet != NULL) {
-               rcp = ssp->smk_packet;
+               rcp = ssp->smk_packet->smk_known;
                slen = strlen(rcp) + 1;
        }
 
@@ -3348,7 +3466,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent)
                return;
 
        ssp = sk->sk_security;
-       ssp->smk_in = skp->smk_known;
+       ssp->smk_in = skp;
        ssp->smk_out = skp;
        /* cssp->smk_packet is already set in smack_inet_csk_clone() */
 }
@@ -3408,7 +3526,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
         * Receiving a packet requires that the other end be able to write
         * here. Read access is not required.
         */
-       rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad);
+       rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad);
        if (rc != 0)
                return rc;
 
@@ -3452,7 +3570,7 @@ static void smack_inet_csk_clone(struct sock *sk,
 
        if (req->peer_secid != 0) {
                skp = smack_from_secid(req->peer_secid);
-               ssp->smk_packet = skp->smk_known;
+               ssp->smk_packet = skp;
        } else
                ssp->smk_packet = NULL;
 }
@@ -3506,11 +3624,12 @@ static void smack_key_free(struct key *key)
  * an error code otherwise
  */
 static int smack_key_permission(key_ref_t key_ref,
-                               const struct cred *cred, key_perm_t perm)
+                               const struct cred *cred, unsigned perm)
 {
        struct key *keyp;
        struct smk_audit_info ad;
        struct smack_known *tkp = smk_of_task(cred->security);
+       int request = 0;
 
        keyp = key_ref_to_ptr(key_ref);
        if (keyp == NULL)
@@ -3531,7 +3650,11 @@ 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);
+       if (perm & KEY_NEED_READ)
+               request = MAY_READ;
+       if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR))
+               request = MAY_WRITE;
+       return smk_access(tkp, keyp->security, request, &ad);
 }
 #endif /* CONFIG_KEYS */
 
index 3198cfe1dcc69fb0bcc158940c030cd125105ed5..32b248820840e76b7db365730f12a2f9eb7b29d0 100644 (file)
@@ -53,6 +53,7 @@ enum smk_inos {
        SMK_REVOKE_SUBJ = 18,   /* set rules with subject label to '-' */
        SMK_CHANGE_RULE = 19,   /* change or add rules (long labels) */
        SMK_SYSLOG      = 20,   /* change syslog label) */
+       SMK_PTRACE      = 21,   /* set ptrace rule */
 };
 
 /*
@@ -100,6 +101,15 @@ struct smack_known *smack_onlycap;
  */
 struct smack_known *smack_syslog_label;
 
+/*
+ * Ptrace current rule
+ * SMACK_PTRACE_DEFAULT    regular smack ptrace rules (/proc based)
+ * SMACK_PTRACE_EXACT      labels must match, but can be overriden with
+ *                        CAP_SYS_PTRACE
+ * SMACK_PTRACE_DRACONIAN  lables must match, CAP_SYS_PTRACE has no effect
+ */
+int smack_ptrace_rule = SMACK_PTRACE_DEFAULT;
+
 /*
  * Certain IP addresses may be designated as single label hosts.
  * Packets are sent there unlabeled, but only from tasks that
@@ -1183,7 +1193,7 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
 
        data[count] = '\0';
 
-       rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%d %s",
+       rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%u %s",
                &host[0], &host[1], &host[2], &host[3], &m, smack);
        if (rc != 6) {
                rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
@@ -2243,6 +2253,68 @@ static const struct file_operations smk_syslog_ops = {
 };
 
 
+/**
+ * smk_read_ptrace - read() for /smack/ptrace
+ * @filp: file pointer, not actually used
+ * @buf: where to put the result
+ * @count: maximum to send along
+ * @ppos: where to start
+ *
+ * Returns number of bytes read or error code, as appropriate
+ */
+static ssize_t smk_read_ptrace(struct file *filp, char __user *buf,
+                              size_t count, loff_t *ppos)
+{
+       char temp[32];
+       ssize_t rc;
+
+       if (*ppos != 0)
+               return 0;
+
+       sprintf(temp, "%d\n", smack_ptrace_rule);
+       rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
+       return rc;
+}
+
+/**
+ * smk_write_ptrace - write() for /smack/ptrace
+ * @file: file pointer
+ * @buf: data from user space
+ * @count: bytes sent
+ * @ppos: where to start - must be 0
+ */
+static ssize_t smk_write_ptrace(struct file *file, const char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       char temp[32];
+       int i;
+
+       if (!smack_privileged(CAP_MAC_ADMIN))
+               return -EPERM;
+
+       if (*ppos != 0 || count >= sizeof(temp) || count == 0)
+               return -EINVAL;
+
+       if (copy_from_user(temp, buf, count) != 0)
+               return -EFAULT;
+
+       temp[count] = '\0';
+
+       if (sscanf(temp, "%d", &i) != 1)
+               return -EINVAL;
+       if (i < SMACK_PTRACE_DEFAULT || i > SMACK_PTRACE_MAX)
+               return -EINVAL;
+       smack_ptrace_rule = i;
+
+       return count;
+}
+
+static const struct file_operations smk_ptrace_ops = {
+       .write          = smk_write_ptrace,
+       .read           = smk_read_ptrace,
+       .llseek         = default_llseek,
+};
+
 /**
  * smk_fill_super - fill the smackfs superblock
  * @sb: the empty superblock
@@ -2296,6 +2368,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
                        "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR},
                [SMK_SYSLOG] = {
                        "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR},
+               [SMK_PTRACE] = {
+                       "ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR},
                /* last one */
                        {""}
        };