2
0
mirror of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git synced 2025-09-04 20:19:47 +08:00

ipe/stable-6.16 PR 20250527

-----BEGIN PGP SIGNATURE-----
 
 iIcEABYIAC8WIQQzmBmZPBN6m/hUJmnyomI6a/yO7QUCaDZldREcd3VmYW5Aa2Vy
 bmVsLm9yZwAKCRDyomI6a/yO7eT7AQCSU1qiLEHpKEbxRtPyD9m6OBVRrS9joKEn
 zABAi00GEgD8C11CKWFemqaL6zexg6c0k51y90K1S1SPZ6pY9HwzZAY=
 =c1Gi
 -----END PGP SIGNATURE-----

Merge tag 'ipe-pr-20250527' of git://git.kernel.org/pub/scm/linux/kernel/git/wufan/ipe

Pull IPE update from Fan Wu:
 "A single commit from Jasjiv Singh, that adds an errno field to IPE
  policy load auditing to log failures with error details, not just
  successes.

  This improves the security audit trail and helps diagnose policy
  deployment issues"

* tag 'ipe-pr-20250527' of git://git.kernel.org/pub/scm/linux/kernel/git/wufan/ipe:
  ipe: add errno field to IPE policy load auditing
This commit is contained in:
Linus Torvalds 2025-05-29 08:01:53 -07:00
commit 12e9b9e522
5 changed files with 112 additions and 44 deletions

View File

@ -423,7 +423,7 @@ Field descriptions:
Event Example:: 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=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 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 descriptions:
+----------------+------------+-----------+---------------------------------------------------+ +----------------+------------+-----------+-------------------------------------------------------------+
| Field | Value Type | Optional? | Description of Value | | Field | Value Type | Optional? | Description of Value |
+================+============+===========+===================================================+ +================+============+===========+=============================================================+
| policy_name | string | No | The policy_name | | policy_name | string | Yes | The policy_name |
+----------------+------------+-----------+---------------------------------------------------+ +----------------+------------+-----------+-------------------------------------------------------------+
| policy_version | string | No | The policy_version | | policy_version | string | Yes | The policy_version |
+----------------+------------+-----------+---------------------------------------------------+ +----------------+------------+-----------+-------------------------------------------------------------+
| policy_digest | string | No | The policy hash | | policy_digest | string | Yes | The policy hash |
+----------------+------------+-----------+---------------------------------------------------+ +----------------+------------+-----------+-------------------------------------------------------------+
| auid | integer | No | The login user ID | | auid | integer | No | The login user ID |
+----------------+------------+-----------+---------------------------------------------------+ +----------------+------------+-----------+-------------------------------------------------------------+
| ses | integer | No | The login session ID | | ses | integer | No | The login session ID |
+----------------+------------+-----------+---------------------------------------------------+ +----------------+------------+-----------+-------------------------------------------------------------+
| lsm | string | No | The lsm name associated with the event | | lsm | string | No | The lsm name associated with the event |
+----------------+------------+-----------+---------------------------------------------------+ +----------------+------------+-----------+-------------------------------------------------------------+
| res | integer | No | The result of the audited operation(success/fail) | | 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 1404 AUDIT_MAC_STATUS
^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^

View File

@ -21,6 +21,8 @@
#define AUDIT_POLICY_LOAD_FMT "policy_name=\"%s\" policy_version=%hu.%hu.%hu "\ #define AUDIT_POLICY_LOAD_FMT "policy_name=\"%s\" policy_version=%hu.%hu.%hu "\
"policy_digest=" IPE_AUDIT_HASH_ALG ":" "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\" "\ #define AUDIT_OLD_ACTIVE_POLICY_FMT "old_active_pol_name=\"%s\" "\
"old_active_pol_version=%hu.%hu.%hu "\ "old_active_pol_version=%hu.%hu.%hu "\
"old_policy_digest=" IPE_AUDIT_HASH_ALG ":" "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. * ipe_audit_policy_load() - Audit a policy loading event.
* @p: Supplies a pointer to the policy to audit. * @p: Supplies a pointer to the policy to audit or an error pointer.
*/ */
void ipe_audit_policy_load(const struct ipe_policy *const p) void ipe_audit_policy_load(const struct ipe_policy *const p)
{ {
struct audit_buffer *ab; struct audit_buffer *ab;
int err = 0;
ab = audit_log_start(audit_context(), GFP_KERNEL, ab = audit_log_start(audit_context(), GFP_KERNEL,
AUDIT_IPE_POLICY_LOAD); AUDIT_IPE_POLICY_LOAD);
if (!ab) if (!ab)
return; return;
if (!IS_ERR(p)) {
audit_policy(ab, AUDIT_POLICY_LOAD_FMT, p); audit_policy(ab, AUDIT_POLICY_LOAD_FMT, p);
audit_log_format(ab, " auid=%u ses=%u lsm=ipe res=1", } 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)), from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current)); audit_get_sessionid(current), !err, err);
audit_log_end(ab); audit_log_end(ab);
} }

View File

@ -133,6 +133,8 @@ static ssize_t getenforce(struct file *f, char __user *data,
* * %-ERANGE - Policy version number overflow * * %-ERANGE - Policy version number overflow
* * %-EINVAL - Policy version parsing error * * %-EINVAL - Policy version parsing error
* * %-EEXIST - Same name policy already deployed * * %-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, static ssize_t new_policy(struct file *f, const char __user *data,
size_t len, loff_t *offset) 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; char *copy = NULL;
int rc = 0; int rc = 0;
if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN)) if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN)) {
return -EPERM; rc = -EPERM;
goto out;
}
copy = memdup_user_nul(data, len); copy = memdup_user_nul(data, len);
if (IS_ERR(copy)) if (IS_ERR(copy)) {
return PTR_ERR(copy); rc = PTR_ERR(copy);
copy = NULL;
goto out;
}
p = ipe_new_policy(NULL, 0, copy, len); p = ipe_new_policy(NULL, 0, copy, len);
if (IS_ERR(p)) { if (IS_ERR(p)) {
@ -158,12 +165,14 @@ static ssize_t new_policy(struct file *f, const char __user *data,
if (rc) if (rc)
goto out; goto out;
ipe_audit_policy_load(p);
out: out:
if (rc < 0)
ipe_free_policy(p);
kfree(copy); 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; return (rc < 0) ? rc : len;
} }

View File

@ -84,8 +84,11 @@ static int set_pkcs7_data(void *ctx, const void *data, size_t len,
* ipe_new_policy. * ipe_new_policy.
* *
* Context: Requires root->i_rwsem to be held. * Context: Requires root->i_rwsem to be held.
* Return: %0 on success. If an error occurs, the function will return * Return:
* the -errno. * * %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, int ipe_update_policy(struct inode *root, const char *text, size_t textlen,
const char *pkcs7, size_t pkcs7len) const char *pkcs7, size_t pkcs7len)
@ -150,6 +153,8 @@ err:
* * %-ENOMEM - Out of memory (OOM) * * %-ENOMEM - Out of memory (OOM)
* * %-ERANGE - Policy version number overflow * * %-ERANGE - Policy version number overflow
* * %-EINVAL - Policy version parsing error * * %-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, struct ipe_policy *ipe_new_policy(const char *text, size_t textlen,
const char *pkcs7, size_t pkcs7len) const char *pkcs7, size_t pkcs7len)

View File

@ -12,6 +12,7 @@
#include "policy.h" #include "policy.h"
#include "eval.h" #include "eval.h"
#include "fs.h" #include "fs.h"
#include "audit.h"
#define MAX_VERSION_SIZE ARRAY_SIZE("65535.65535.65535") #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, * On success this updates the policy represented by $name,
* in-place. * in-place.
* *
* Return: Length of buffer written on success. If an error occurs, * Return:
* the function will return the -errno. * * 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, static ssize_t update_policy(struct file *f, const char __user *data,
size_t len, loff_t *offset) 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; char *copy = NULL;
int rc = 0; int rc = 0;
if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN)) if (!file_ns_capable(f, &init_user_ns, CAP_MAC_ADMIN)) {
return -EPERM; rc = -EPERM;
goto out;
}
copy = memdup_user(data, len); copy = memdup_user(data, len);
if (IS_ERR(copy)) if (IS_ERR(copy)) {
return PTR_ERR(copy); rc = PTR_ERR(copy);
copy = NULL;
goto out;
}
root = d_inode(f->f_path.dentry->d_parent); root = d_inode(f->f_path.dentry->d_parent);
inode_lock(root); inode_lock(root);
rc = ipe_update_policy(root, NULL, 0, copy, len); rc = ipe_update_policy(root, NULL, 0, copy, len);
inode_unlock(root); inode_unlock(root);
out:
kfree(copy); kfree(copy);
if (rc) if (rc) {
ipe_audit_policy_load(ERR_PTR(rc));
return rc; return rc;
}
return len; return len;
} }