diff options
-rw-r--r-- | Documentation/admin-guide/LSM/ipe.rst | 69 | ||||
-rw-r--r-- | security/ipe/audit.c | 19 | ||||
-rw-r--r-- | security/ipe/fs.c | 25 | ||||
-rw-r--r-- | security/ipe/policy.c | 17 | ||||
-rw-r--r-- | security/ipe/policy_fs.c | 28 |
5 files changed, 113 insertions, 45 deletions
diff --git a/Documentation/admin-guide/LSM/ipe.rst b/Documentation/admin-guide/LSM/ipe.rst index f93a467db628..dc7088451f9d 100644 --- a/Documentation/admin-guide/LSM/ipe.rst +++ b/Documentation/admin-guide/LSM/ipe.rst @@ -423,7 +423,7 @@ Field descriptions: Event Example:: - type=1422 audit(1653425529.927:53): policy_name="boot_verified" policy_version=0.0.0 policy_digest=sha256:820EEA5B40CA42B51F68962354BA083122A20BB846F26765076DD8EED7B8F4DB auid=4294967295 ses=4294967295 lsm=ipe res=1 + type=1422 audit(1653425529.927:53): policy_name="boot_verified" policy_version=0.0.0 policy_digest=sha256:820EEA5B40CA42B51F68962354BA083122A20BB846F26765076DD8EED7B8F4DB auid=4294967295 ses=4294967295 lsm=ipe res=1 errno=0 type=1300 audit(1653425529.927:53): arch=c000003e syscall=1 success=yes exit=2567 a0=3 a1=5596fcae1fb0 a2=a07 a3=2 items=0 ppid=184 pid=229 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=4294967295 comm="python3" exe="/usr/bin/python3.10" key=(null) type=1327 audit(1653425529.927:53): PROCTITLE proctitle=707974686F6E3300746573742F6D61696E2E7079002D66002E2E @@ -433,24 +433,55 @@ This record will always be emitted in conjunction with a ``AUDITSYSCALL`` record Field descriptions: -+----------------+------------+-----------+---------------------------------------------------+ -| Field | Value Type | Optional? | Description of Value | -+================+============+===========+===================================================+ -| policy_name | string | No | The policy_name | -+----------------+------------+-----------+---------------------------------------------------+ -| policy_version | string | No | The policy_version | -+----------------+------------+-----------+---------------------------------------------------+ -| policy_digest | string | No | The policy hash | -+----------------+------------+-----------+---------------------------------------------------+ -| auid | integer | No | The login user ID | -+----------------+------------+-----------+---------------------------------------------------+ -| ses | integer | No | The login session ID | -+----------------+------------+-----------+---------------------------------------------------+ -| lsm | string | No | The lsm name associated with the event | -+----------------+------------+-----------+---------------------------------------------------+ -| res | integer | No | The result of the audited operation(success/fail) | -+----------------+------------+-----------+---------------------------------------------------+ - ++----------------+------------+-----------+-------------------------------------------------------------+ +| Field | Value Type | Optional? | Description of Value | ++================+============+===========+=============================================================+ +| policy_name | string | Yes | The policy_name | ++----------------+------------+-----------+-------------------------------------------------------------+ +| policy_version | string | Yes | The policy_version | ++----------------+------------+-----------+-------------------------------------------------------------+ +| policy_digest | string | Yes | The policy hash | ++----------------+------------+-----------+-------------------------------------------------------------+ +| auid | integer | No | The login user ID | ++----------------+------------+-----------+-------------------------------------------------------------+ +| ses | integer | No | The login session ID | ++----------------+------------+-----------+-------------------------------------------------------------+ +| lsm | string | No | The lsm name associated with the event | ++----------------+------------+-----------+-------------------------------------------------------------+ +| res | integer | No | The result of the audited operation(success/fail) | ++----------------+------------+-----------+-------------------------------------------------------------+ +| errno | integer | No | Error code from policy loading operations (see table below) | ++----------------+------------+-----------+-------------------------------------------------------------+ + +Policy error codes (errno): + +The following table lists the error codes that may appear in the errno field while loading or updating the policy: + ++----------------+--------------------------------------------------------+ +| Error Code | Description | ++================+========================================================+ +| 0 | Success | ++----------------+--------------------------------------------------------+ +| -EPERM | Insufficient permission | ++----------------+--------------------------------------------------------+ +| -EEXIST | Same name policy already deployed | ++----------------+--------------------------------------------------------+ +| -EBADMSG | Policy is invalid | ++----------------+--------------------------------------------------------+ +| -ENOMEM | Out of memory (OOM) | ++----------------+--------------------------------------------------------+ +| -ERANGE | Policy version number overflow | ++----------------+--------------------------------------------------------+ +| -EINVAL | Policy version parsing error | ++----------------+--------------------------------------------------------+ +| -ENOKEY | Key used to sign the IPE policy not found in keyring | ++----------------+--------------------------------------------------------+ +| -EKEYREJECTED | Policy signature verification failed | ++----------------+--------------------------------------------------------+ +| -ESTALE | Attempting to update an IPE policy with older version | ++----------------+--------------------------------------------------------+ +| -ENOENT | Policy was deleted while updating | ++----------------+--------------------------------------------------------+ 1404 AUDIT_MAC_STATUS ^^^^^^^^^^^^^^^^^^^^^ diff --git a/security/ipe/audit.c b/security/ipe/audit.c index f05f0caa4850..9668ecc5acd5 100644 --- a/security/ipe/audit.c +++ b/security/ipe/audit.c @@ -21,6 +21,8 @@ #define AUDIT_POLICY_LOAD_FMT "policy_name=\"%s\" policy_version=%hu.%hu.%hu "\ "policy_digest=" IPE_AUDIT_HASH_ALG ":" +#define AUDIT_POLICY_LOAD_NULL_FMT "policy_name=? policy_version=? "\ + "policy_digest=?" #define AUDIT_OLD_ACTIVE_POLICY_FMT "old_active_pol_name=\"%s\" "\ "old_active_pol_version=%hu.%hu.%hu "\ "old_policy_digest=" IPE_AUDIT_HASH_ALG ":" @@ -248,22 +250,29 @@ void ipe_audit_policy_activation(const struct ipe_policy *const op, } /** - * ipe_audit_policy_load() - Audit a policy being loaded into the kernel. - * @p: Supplies a pointer to the policy to audit. + * ipe_audit_policy_load() - Audit a policy loading event. + * @p: Supplies a pointer to the policy to audit or an error pointer. */ void ipe_audit_policy_load(const struct ipe_policy *const p) { struct audit_buffer *ab; + int err = 0; ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_IPE_POLICY_LOAD); if (!ab) return; - audit_policy(ab, AUDIT_POLICY_LOAD_FMT, p); - audit_log_format(ab, " auid=%u ses=%u lsm=ipe res=1", + if (!IS_ERR(p)) { + audit_policy(ab, AUDIT_POLICY_LOAD_FMT, p); + } else { + audit_log_format(ab, AUDIT_POLICY_LOAD_NULL_FMT); + err = PTR_ERR(p); + } + + audit_log_format(ab, " auid=%u ses=%u lsm=ipe res=%d errno=%d", from_kuid(&init_user_ns, audit_get_loginuid(current)), - audit_get_sessionid(current)); + audit_get_sessionid(current), !err, err); audit_log_end(ab); } diff --git a/security/ipe/fs.c b/security/ipe/fs.c index 5b6d19fb844a..f40e50bfd2e7 100644 --- a/security/ipe/fs.c +++ b/security/ipe/fs.c @@ -133,6 +133,8 @@ static ssize_t getenforce(struct file *f, char __user *data, * * %-ERANGE - Policy version number overflow * * %-EINVAL - Policy version parsing error * * %-EEXIST - Same name policy already deployed + * * %-ENOKEY - Policy signing key not found + * * %-EKEYREJECTED - Policy signature verification failed */ static ssize_t new_policy(struct file *f, const char __user *data, size_t len, loff_t *offset) @@ -141,12 +143,17 @@ static ssize_t new_policy(struct file *f, const char __user *data, char *copy = NULL; int rc = 0; - if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN)) - return -EPERM; + if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN)) { + rc = -EPERM; + goto out; + } copy = memdup_user_nul(data, len); - if (IS_ERR(copy)) - return PTR_ERR(copy); + if (IS_ERR(copy)) { + rc = PTR_ERR(copy); + copy = NULL; + goto out; + } p = ipe_new_policy(NULL, 0, copy, len); if (IS_ERR(p)) { @@ -158,12 +165,14 @@ static ssize_t new_policy(struct file *f, const char __user *data, if (rc) goto out; - ipe_audit_policy_load(p); - out: - if (rc < 0) - ipe_free_policy(p); kfree(copy); + if (rc < 0) { + ipe_free_policy(p); + ipe_audit_policy_load(ERR_PTR(rc)); + } else { + ipe_audit_policy_load(p); + } return (rc < 0) ? rc : len; } diff --git a/security/ipe/policy.c b/security/ipe/policy.c index b628f696e32b..1c58c29886e8 100644 --- a/security/ipe/policy.c +++ b/security/ipe/policy.c @@ -84,8 +84,11 @@ static int set_pkcs7_data(void *ctx, const void *data, size_t len, * ipe_new_policy. * * Context: Requires root->i_rwsem to be held. - * Return: %0 on success. If an error occurs, the function will return - * the -errno. + * Return: + * * %0 - Success + * * %-ENOENT - Policy was deleted while updating + * * %-EINVAL - Policy name mismatch + * * %-ESTALE - Policy version too old */ int ipe_update_policy(struct inode *root, const char *text, size_t textlen, const char *pkcs7, size_t pkcs7len) @@ -146,10 +149,12 @@ err: * * Return: * * a pointer to the ipe_policy structure - Success - * * %-EBADMSG - Policy is invalid - * * %-ENOMEM - Out of memory (OOM) - * * %-ERANGE - Policy version number overflow - * * %-EINVAL - Policy version parsing error + * * %-EBADMSG - Policy is invalid + * * %-ENOMEM - Out of memory (OOM) + * * %-ERANGE - Policy version number overflow + * * %-EINVAL - Policy version parsing error + * * %-ENOKEY - Policy signing key not found + * * %-EKEYREJECTED - Policy signature verification failed */ struct ipe_policy *ipe_new_policy(const char *text, size_t textlen, const char *pkcs7, size_t pkcs7len) diff --git a/security/ipe/policy_fs.c b/security/ipe/policy_fs.c index 4cb4dd7f5236..db26032ccbe1 100644 --- a/security/ipe/policy_fs.c +++ b/security/ipe/policy_fs.c @@ -12,6 +12,7 @@ #include "policy.h" #include "eval.h" #include "fs.h" +#include "audit.h" #define MAX_VERSION_SIZE ARRAY_SIZE("65535.65535.65535") @@ -286,8 +287,13 @@ static ssize_t getactive(struct file *f, char __user *data, * On success this updates the policy represented by $name, * in-place. * - * Return: Length of buffer written on success. If an error occurs, - * the function will return the -errno. + * Return: + * * Length of buffer written - Success + * * %-EPERM - Insufficient permission + * * %-ENOMEM - Out of memory (OOM) + * * %-ENOENT - Policy was deleted while updating + * * %-EINVAL - Policy name mismatch + * * %-ESTALE - Policy version too old */ static ssize_t update_policy(struct file *f, const char __user *data, size_t len, loff_t *offset) @@ -296,21 +302,29 @@ static ssize_t update_policy(struct file *f, const char __user *data, char *copy = NULL; int rc = 0; - if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN)) - return -EPERM; + if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN)) { + rc = -EPERM; + goto out; + } copy = memdup_user(data, len); - if (IS_ERR(copy)) - return PTR_ERR(copy); + if (IS_ERR(copy)) { + rc = PTR_ERR(copy); + copy = NULL; + goto out; + } root = d_inode(f->f_path.dentry->d_parent); inode_lock(root); rc = ipe_update_policy(root, NULL, 0, copy, len); inode_unlock(root); +out: kfree(copy); - if (rc) + if (rc) { + ipe_audit_policy_load(ERR_PTR(rc)); return rc; + } return len; } |