[RFC PATCH v2 29/41] signal: report the sender's UUID or GUID uid in si_uid_r

Jan Koester jan.koester at tuxist.de
Wed Oct 21 03:15:49 UTC 2026


si_uid is 32 bits, so a signal from a UUID or GUID user names the
overflow uid as its sender, and so do SIGCHLD and waitid() for such a
child.

Add si_uid_r, the sender's uid as __kernel_uid_r_t, to siginfo_t. union
__sifields has no room that all kinds of signals with si_uid share, so
it lives at a fixed offset (96) in the padding of siginfo_t, the same
in every layout and ABI, compat_siginfo included; kernel_siginfo grows
to cover it. The kernel sets it wherever it sets si_uid, through
siginfo_set_uid() and siginfo_set_kernel_uid(), maps it into the
receiver's user namespace like si_uid, and it is UID_R_NONE where
nobody set it. Signals queued from userspace carry what the sender put
there, exactly like si_uid.

signalfd_siginfo gets ssi_uid_r from its padding, and waitid() (also
through io_uring, which keeps its waitid_info in the async data now, as
it no longer fits into the command) fills in si_uid_r.

Assisted-by: Claude:claude-opus-5-5

Signed-off-by: Jan Koester <jan.koester at tuxist.de>
---
 fs/signalfd.c                      |  3 ++
 include/linux/compat.h             |  6 ++++
 include/linux/ptrace.h             |  2 +-
 include/linux/signal.h             | 22 ++++++++++++++
 include/linux/signal_types.h       |  5 +++-
 include/uapi/asm-generic/siginfo.h | 17 +++++++++++
 include/uapi/linux/signalfd.h      |  4 ++-
 io_uring/waitid.c                  | 32 ++++++++++++--------
 io_uring/waitid.h                  |  1 +
 ipc/mqueue.c                       |  4 +--
 kernel/exit.c                      | 18 +++++++++--
 kernel/exit.h                      |  3 ++
 kernel/signal.c                    | 48 ++++++++++++++++++++----------
 13 files changed, 129 insertions(+), 36 deletions(-)

diff --git a/fs/signalfd.c b/fs/signalfd.c
index dff53745e3..8bca9d7f01 100644
--- a/fs/signalfd.c
+++ b/fs/signalfd.c
@@ -90,6 +90,7 @@ static int signalfd_copyinfo(struct iov_iter *to, kernel_siginfo_t const *kinfo)
 	case SIL_KILL:
 		new.ssi_pid = kinfo->si_pid;
 		new.ssi_uid = kinfo->si_uid;
+		new.ssi_uid_r = kinfo->si_uid_r;
 		break;
 	case SIL_TIMER:
 		new.ssi_tid = kinfo->si_tid;
@@ -125,6 +126,7 @@ static int signalfd_copyinfo(struct iov_iter *to, kernel_siginfo_t const *kinfo)
 	case SIL_CHLD:
 		new.ssi_pid    = kinfo->si_pid;
 		new.ssi_uid    = kinfo->si_uid;
+		new.ssi_uid_r  = kinfo->si_uid_r;
 		new.ssi_status = kinfo->si_status;
 		new.ssi_utime  = kinfo->si_utime;
 		new.ssi_stime  = kinfo->si_stime;
@@ -135,6 +137,7 @@ static int signalfd_copyinfo(struct iov_iter *to, kernel_siginfo_t const *kinfo)
 		 */
 		new.ssi_pid = kinfo->si_pid;
 		new.ssi_uid = kinfo->si_uid;
+		new.ssi_uid_r = kinfo->si_uid_r;
 		new.ssi_ptr = (long) kinfo->si_ptr;
 		new.ssi_int = kinfo->si_int;
 		break;
diff --git a/include/linux/compat.h b/include/linux/compat.h
index 8da0a15c95..4b85059008 100644
--- a/include/linux/compat.h
+++ b/include/linux/compat.h
@@ -169,6 +169,12 @@ typedef struct compat_siginfo {
 	union {
 		int _pad[128/sizeof(int) - 3];
 
+		/* si_uid_r, at __SI_UID_R_OFFSET like in siginfo_t */
+		struct {
+			int _uid_r_pad[__SI_UID_R_OFFSET / sizeof(int) - 3];
+			__kernel_uid_r_t _uid_r;
+		} _sir;
+
 		/* kill() */
 		struct {
 			compat_pid_t _pid;	/* sender's pid */
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 2839d5c8ea..1d6d41c67f 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -347,7 +347,7 @@ static inline void user_single_step_report(struct pt_regs *regs)
 	info.si_errno = 0;
 	info.si_code = SI_USER;
 	info.si_pid = 0;
-	info.si_uid = 0;
+	siginfo_set_kernel_uid(&info);
 	force_sig_info(&info);
 }
 #endif
diff --git a/include/linux/signal.h b/include/linux/signal.h
index f19816832f..928e67e283 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -6,6 +6,7 @@
 #include <linux/list.h>
 #include <linux/signal_types.h>
 #include <linux/string.h>
+#include <linux/uidgid.h>
 
 struct task_struct;
 
@@ -23,6 +24,27 @@ static inline void clear_siginfo(kernel_siginfo_t *info)
 	memset(info, 0, sizeof(*info));
 }
 
+struct user_namespace;
+
+/*
+ * Sets si_uid and si_uid_r to @uid as seen from @ns (the receiver's user
+ * namespace), the overflow id if it has no mapping there.
+ */
+static inline void siginfo_set_uid(kernel_siginfo_t *info,
+				   struct user_namespace *ns, kuid_t uid)
+{
+	info->si_uid = from_kuid_munged(ns, uid);
+	from_kuid_r_munged(ns, uid, &info->si_uid_r);
+}
+
+/* si_uid and si_uid_r of a signal from the kernel: 0 */
+static inline void siginfo_set_kernel_uid(kernel_siginfo_t *info)
+{
+	info->si_uid = 0;
+	memset(&info->si_uid_r, 0, sizeof(info->si_uid_r));
+	info->si_uid_r.type = UID_R_LEGACY;
+}
+
 #define SI_EXPANSION_SIZE (sizeof(struct siginfo) - sizeof(struct kernel_siginfo))
 
 static inline void copy_siginfo_to_external(siginfo_t *to,
diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h
index caf4f7a59a..eaf922e443 100644
--- a/include/linux/signal_types.h
+++ b/include/linux/signal_types.h
@@ -10,7 +10,10 @@
 #include <uapi/linux/signal.h>
 
 typedef struct kernel_siginfo {
-	__SIGINFO;
+	union {
+		__SIGINFO;
+		__SIGINFO_UID_R;
+	};
 } kernel_siginfo_t;
 
 struct ucounts;
diff --git a/include/uapi/asm-generic/siginfo.h b/include/uapi/asm-generic/siginfo.h
index 5a1ca43b5f..e8f32c942b 100644
--- a/include/uapi/asm-generic/siginfo.h
+++ b/include/uapi/asm-generic/siginfo.h
@@ -4,6 +4,7 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
+#include <linux/uidgid_r.h>
 
 typedef union sigval {
 	int sival_int;
@@ -131,9 +132,24 @@ struct {				\
 }
 #endif /* __ARCH_HAS_SWAPPED_SIGINFO */
 
+/*
+ * The sender's uid as __kernel_uid_r_t (a UUID or GUID too), for the
+ * signals with si_pid and si_uid. It lives at the same offset in every
+ * layout and ABI, past the end of union __sifields; UID_R_NONE where the
+ * kernel doesn't set it.
+ */
+#define __SI_UID_R_OFFSET	96
+
+#define __SIGINFO_UID_R						\
+struct {							\
+	int _uid_r_pad[__SI_UID_R_OFFSET / sizeof(int)];	\
+	__kernel_uid_r_t _uid_r;				\
+} _sir
+
 typedef struct siginfo {
 	union {
 		__SIGINFO;
+		__SIGINFO_UID_R;
 		int _si_pad[SI_MAX_SIZE/sizeof(int)];
 	};
 } __ARCH_SI_ATTRIBUTES siginfo_t;
@@ -143,6 +159,7 @@ typedef struct siginfo {
  */
 #define si_pid		_sifields._kill._pid
 #define si_uid		_sifields._kill._uid
+#define si_uid_r	_sir._uid_r
 #define si_tid		_sifields._timer._tid
 #define si_overrun	_sifields._timer._overrun
 #define si_sys_private  _sifields._timer._sys_private
diff --git a/include/uapi/linux/signalfd.h b/include/uapi/linux/signalfd.h
index 83429a05b6..471bafc539 100644
--- a/include/uapi/linux/signalfd.h
+++ b/include/uapi/linux/signalfd.h
@@ -10,6 +10,7 @@
 #define _UAPI_LINUX_SIGNALFD_H
 
 #include <linux/types.h>
+#include <linux/uidgid_r.h>
 /* For O_CLOEXEC and O_NONBLOCK */
 #include <linux/fcntl.h>
 
@@ -39,6 +40,7 @@ struct signalfd_siginfo {
 	__s32 ssi_syscall;
 	__u64 ssi_call_addr;
 	__u32 ssi_arch;
+	__kernel_uid_r_t ssi_uid_r;	/* sender's uid, also a UUID or GUID */
 
 	/*
 	 * Pad strcture to 128 bytes. Remember to update the
@@ -49,7 +51,7 @@ struct signalfd_siginfo {
 	 * comes out of a read(2) and we really don't want to have
 	 * a compat on read(2).
 	 */
-	__u8 __pad[28];
+	__u8 __pad[8];
 };
 
 
diff --git a/io_uring/waitid.c b/io_uring/waitid.c
index 2b75601742..24f27b67d3 100644
--- a/io_uring/waitid.c
+++ b/io_uring/waitid.c
@@ -29,7 +29,6 @@ struct io_waitid {
 	atomic_t refs;
 	struct wait_queue_head *head;
 	struct siginfo __user *infop;
-	struct waitid_info info;
 };
 
 static void io_waitid_free(struct io_kiocb *req)
@@ -40,8 +39,10 @@ static void io_waitid_free(struct io_kiocb *req)
 	io_req_async_data_free(req);
 }
 
-static bool io_waitid_compat_copy_si(struct io_waitid *iw, int signo)
+static bool io_waitid_compat_copy_si(struct io_kiocb *req, int signo)
 {
+	struct io_waitid *iw = io_kiocb_to_cmd(req, struct io_waitid);
+	struct io_waitid_async *iwa = req->async_data;
 	struct compat_siginfo __user *infop;
 	bool ret;
 
@@ -52,10 +53,12 @@ static bool io_waitid_compat_copy_si(struct io_waitid *iw, int signo)
 
 	unsafe_put_user(signo, &infop->si_signo, Efault);
 	unsafe_put_user(0, &infop->si_errno, Efault);
-	unsafe_put_user(iw->info.cause, &infop->si_code, Efault);
-	unsafe_put_user(iw->info.pid, &infop->si_pid, Efault);
-	unsafe_put_user(iw->info.uid, &infop->si_uid, Efault);
-	unsafe_put_user(iw->info.status, &infop->si_status, Efault);
+	unsafe_put_user(iwa->info.cause, &infop->si_code, Efault);
+	unsafe_put_user(iwa->info.pid, &infop->si_pid, Efault);
+	unsafe_put_user(iwa->info.uid, &infop->si_uid, Efault);
+	unsafe_copy_to_user((char __user *)&infop->_sifields._sir._uid_r,
+			    (const char *)&iwa->info.uid_r, sizeof(iwa->info.uid_r), Efault);
+	unsafe_put_user(iwa->info.status, &infop->si_status, Efault);
 	ret = true;
 done:
 	user_write_access_end();
@@ -68,23 +71,26 @@ static bool io_waitid_compat_copy_si(struct io_waitid *iw, int signo)
 static bool io_waitid_copy_si(struct io_kiocb *req, int signo)
 {
 	struct io_waitid *iw = io_kiocb_to_cmd(req, struct io_waitid);
+	struct io_waitid_async *iwa = req->async_data;
 	bool ret;
 
 	if (!iw->infop)
 		return true;
 
 	if (io_is_compat(req->ctx))
-		return io_waitid_compat_copy_si(iw, signo);
+		return io_waitid_compat_copy_si(req, signo);
 
 	if (!user_write_access_begin(iw->infop, sizeof(*iw->infop)))
 		return false;
 
 	unsafe_put_user(signo, &iw->infop->si_signo, Efault);
 	unsafe_put_user(0, &iw->infop->si_errno, Efault);
-	unsafe_put_user(iw->info.cause, &iw->infop->si_code, Efault);
-	unsafe_put_user(iw->info.pid, &iw->infop->si_pid, Efault);
-	unsafe_put_user(iw->info.uid, &iw->infop->si_uid, Efault);
-	unsafe_put_user(iw->info.status, &iw->infop->si_status, Efault);
+	unsafe_put_user(iwa->info.cause, &iw->infop->si_code, Efault);
+	unsafe_put_user(iwa->info.pid, &iw->infop->si_pid, Efault);
+	unsafe_put_user(iwa->info.uid, &iw->infop->si_uid, Efault);
+	unsafe_copy_to_user((char __user *)&iw->infop->si_uid_r,
+			    (const char *)&iwa->info.uid_r, sizeof(iwa->info.uid_r), Efault);
+	unsafe_put_user(iwa->info.status, &iw->infop->si_status, Efault);
 	ret = true;
 done:
 	user_write_access_end();
@@ -294,7 +300,7 @@ int io_waitid_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
 	iw->options = READ_ONCE(sqe->file_index);
 	iw->head = NULL;
 	iw->infop = u64_to_user_ptr(READ_ONCE(sqe->addr2));
-	memset(&iw->info, 0, sizeof(iw->info));
+	memset(&iwa->info, 0, sizeof(iwa->info));
 	return 0;
 }
 
@@ -305,7 +311,7 @@ int io_waitid(struct io_kiocb *req, unsigned int issue_flags)
 	struct io_ring_ctx *ctx = req->ctx;
 	int ret;
 
-	ret = kernel_waitid_prepare(&iwa->wo, iw->which, iw->upid, &iw->info,
+	ret = kernel_waitid_prepare(&iwa->wo, iw->which, iw->upid, &iwa->info,
 					iw->options, NULL);
 	if (ret)
 		goto done;
diff --git a/io_uring/waitid.h b/io_uring/waitid.h
index d5544aaf30..60b744a0e8 100644
--- a/io_uring/waitid.h
+++ b/io_uring/waitid.h
@@ -5,6 +5,7 @@
 struct io_waitid_async {
 	struct io_kiocb *req;
 	struct wait_opts wo;
+	struct waitid_info info;
 };
 
 int io_waitid_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index d1dd36a651..f0a319ed97 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -802,8 +802,8 @@ static void __do_notify(struct mqueue_inode_info *info)
 			/* map current pid/uid into info->owner's namespaces */
 			sig_i.si_pid = task_tgid_nr_ns(current,
 						ns_of_pid(info->notify_owner));
-			sig_i.si_uid = from_kuid_munged(info->notify_user_ns,
-						current_uid());
+			siginfo_set_uid(&sig_i, info->notify_user_ns,
+					current_uid());
 			/*
 			 * We can't use kill_pid_info(), this signal should
 			 * bypass check_kill_permission(). It is from kernel
diff --git a/kernel/exit.c b/kernel/exit.c
index 282328d2b4..130234f702 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1185,7 +1185,8 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
 {
 	int state, status;
 	pid_t pid = task_pid_vnr(p);
-	uid_t uid = from_kuid_munged(current_user_ns(), task_uid(p));
+	kuid_t kuid = task_uid(p);
+	uid_t uid = from_kuid_munged(current_user_ns(), kuid);
 	struct waitid_info *infop;
 
 	if (!likely(wo->wo_flags & WEXITED))
@@ -1302,6 +1303,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
 		}
 		infop->pid = pid;
 		infop->uid = uid;
+		from_kuid_r_munged(current_user_ns(), kuid, &infop->uid_r);
 	}
 
 	return pid;
@@ -1343,6 +1345,7 @@ static int wait_task_stopped(struct wait_opts *wo,
 	struct waitid_info *infop;
 	int exit_code, *p_code, why;
 	uid_t uid = 0; /* unneeded, required by compiler */
+	kuid_t kuid = INVALID_UID;
 	pid_t pid;
 
 	/*
@@ -1368,7 +1371,8 @@ static int wait_task_stopped(struct wait_opts *wo,
 	if (!unlikely(wo->wo_flags & WNOWAIT))
 		*p_code = 0;
 
-	uid = from_kuid_munged(current_user_ns(), task_uid(p));
+	kuid = task_uid(p);
+	uid = from_kuid_munged(current_user_ns(), kuid);
 unlock_sig:
 	spin_unlock_irq(&p->sighand->siglock);
 	if (!exit_code)
@@ -1399,6 +1403,7 @@ static int wait_task_stopped(struct wait_opts *wo,
 		infop->status = exit_code;
 		infop->pid = pid;
 		infop->uid = uid;
+		from_kuid_r_munged(current_user_ns(), kuid, &infop->uid_r);
 	}
 	return pid;
 }
@@ -1414,6 +1419,7 @@ static int wait_task_continued(struct wait_opts *wo, struct task_struct *p)
 	struct waitid_info *infop;
 	pid_t pid;
 	uid_t uid;
+	kuid_t kuid;
 
 	if (!unlikely(wo->wo_flags & WCONTINUED))
 		return 0;
@@ -1429,7 +1435,8 @@ static int wait_task_continued(struct wait_opts *wo, struct task_struct *p)
 	}
 	if (!unlikely(wo->wo_flags & WNOWAIT))
 		p->signal->flags &= ~SIGNAL_STOP_CONTINUED;
-	uid = from_kuid_munged(current_user_ns(), task_uid(p));
+	kuid = task_uid(p);
+	uid = from_kuid_munged(current_user_ns(), kuid);
 	spin_unlock_irq(&p->sighand->siglock);
 
 	pid = task_pid_vnr(p);
@@ -1447,6 +1454,7 @@ static int wait_task_continued(struct wait_opts *wo, struct task_struct *p)
 		infop->cause = CLD_CONTINUED;
 		infop->pid = pid;
 		infop->uid = uid;
+		from_kuid_r_munged(current_user_ns(), kuid, &infop->uid_r);
 		infop->status = SIGCONT;
 	}
 	return pid;
@@ -1846,6 +1854,8 @@ SYSCALL_DEFINE5(waitid, int, which, pid_t, upid, struct siginfo __user *,
 	unsafe_put_user(info.cause, &infop->si_code, Efault);
 	unsafe_put_user(info.pid, &infop->si_pid, Efault);
 	unsafe_put_user(info.uid, &infop->si_uid, Efault);
+	unsafe_copy_to_user((char __user *)&infop->si_uid_r,
+			    (const char *)&info.uid_r, sizeof(info.uid_r), Efault);
 	unsafe_put_user(info.status, &infop->si_status, Efault);
 	user_write_access_end();
 	return err;
@@ -1989,6 +1999,8 @@ COMPAT_SYSCALL_DEFINE5(waitid,
 	unsafe_put_user(info.cause, &infop->si_code, Efault);
 	unsafe_put_user(info.pid, &infop->si_pid, Efault);
 	unsafe_put_user(info.uid, &infop->si_uid, Efault);
+	unsafe_copy_to_user((char __user *)&infop->_sifields._sir._uid_r,
+			    (const char *)&info.uid_r, sizeof(info.uid_r), Efault);
 	unsafe_put_user(info.status, &infop->si_status, Efault);
 	user_write_access_end();
 	return err;
diff --git a/kernel/exit.h b/kernel/exit.h
index 278faa26a6..f24a6d6917 100644
--- a/kernel/exit.h
+++ b/kernel/exit.h
@@ -2,9 +2,12 @@
 #ifndef LINUX_WAITID_H
 #define LINUX_WAITID_H
 
+#include <linux/uidgid_r.h>
+
 struct waitid_info {
 	pid_t pid;
 	uid_t uid;
+	__kernel_uid_r_t uid_r;		/* uid as __kernel_uid_r_t */
 	int status;
 	int cause;
 };
diff --git a/kernel/signal.c b/kernel/signal.c
index d31ebcb6ed..af0793d04b 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -602,7 +602,7 @@ static void collect_signal(int sig, struct sigpending *list, kernel_siginfo_t *i
 		info->si_errno = 0;
 		info->si_code = SI_USER;
 		info->si_pid = 0;
-		info->si_uid = 0;
+		siginfo_set_kernel_uid(info);
 	}
 }
 
@@ -1120,9 +1120,8 @@ static int __send_signal_locked(int sig, struct kernel_siginfo *info,
 			q->info.si_pid = task_tgid_nr_ns(current,
 							task_active_pid_ns(t));
 			rcu_read_lock();
-			q->info.si_uid =
-				from_kuid_munged(task_cred_xxx(t, user_ns),
-						 current_uid());
+			siginfo_set_uid(&q->info, task_cred_xxx(t, user_ns),
+					current_uid());
 			rcu_read_unlock();
 			break;
 		case (unsigned long) SEND_SIG_PRIV:
@@ -1131,7 +1130,7 @@ static int __send_signal_locked(int sig, struct kernel_siginfo *info,
 			q->info.si_errno = 0;
 			q->info.si_code = SI_KERNEL;
 			q->info.si_pid = 0;
-			q->info.si_uid = 0;
+			siginfo_set_kernel_uid(&q->info);
 			break;
 		default:
 			copy_siginfo(&q->info, info);
@@ -1229,6 +1228,13 @@ int send_signal_locked(int sig, struct kernel_siginfo *info,
 			info = &rewritten;
 			uid = make_kuid(current_user_ns(), info->si_uid);
 			rewritten.si_uid = from_kuid_munged(t_user_ns, uid);
+			if (rewritten.si_uid_r.type != UID_R_NONE) {
+				kuid_t uid_r = make_kuid_r(current_user_ns(),
+							   &rewritten.si_uid_r);
+
+				from_kuid_r_munged(t_user_ns, uid_r,
+						   &rewritten.si_uid_r);
+			}
 		}
 		rcu_read_unlock();
 #endif
@@ -1684,7 +1690,7 @@ void force_sig(int sig)
 	info.si_errno = 0;
 	info.si_code = SI_KERNEL;
 	info.si_pid = 0;
-	info.si_uid = 0;
+	siginfo_set_kernel_uid(&info);
 	force_sig_info(&info);
 }
 EXPORT_SYMBOL(force_sig);
@@ -1698,7 +1704,7 @@ void force_fatal_sig(int sig)
 	info.si_errno = 0;
 	info.si_code = SI_KERNEL;
 	info.si_pid = 0;
-	info.si_uid = 0;
+	siginfo_set_kernel_uid(&info);
 	force_sig_info_to_task(&info, current, HANDLER_SIG_DFL);
 }
 
@@ -1711,7 +1717,7 @@ void force_exit_sig(int sig)
 	info.si_errno = 0;
 	info.si_code = SI_KERNEL;
 	info.si_pid = 0;
-	info.si_uid = 0;
+	siginfo_set_kernel_uid(&info);
 	force_sig_info_to_task(&info, current, HANDLER_EXIT);
 }
 
@@ -2282,8 +2288,8 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
 	 */
 	rcu_read_lock();
 	info.si_pid = task_pid_nr_ns(tsk, task_active_pid_ns(tsk->parent));
-	info.si_uid = from_kuid_munged(task_cred_xxx(tsk->parent, user_ns),
-				       task_uid(tsk));
+	siginfo_set_uid(&info, task_cred_xxx(tsk->parent, user_ns),
+			task_uid(tsk));
 	rcu_read_unlock();
 
 	task_cputime(tsk, &utime, &stime);
@@ -2377,7 +2383,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk,
 	 */
 	rcu_read_lock();
 	info.si_pid = task_pid_nr_ns(tsk, task_active_pid_ns(parent));
-	info.si_uid = from_kuid_munged(task_cred_xxx(parent, user_ns), task_uid(tsk));
+	siginfo_set_uid(&info, task_cred_xxx(parent, user_ns), task_uid(tsk));
 	rcu_read_unlock();
 
 	task_cputime(tsk, &utime, &stime);
@@ -2582,7 +2588,7 @@ static int ptrace_do_notify(int signr, int exit_code, int why, unsigned long mes
 	info.si_signo = signr;
 	info.si_code = exit_code;
 	info.si_pid = task_pid_vnr(current);
-	info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
+	siginfo_set_uid(&info, current_user_ns(), current_uid());
 
 	/* Let the debugger run.  */
 	return ptrace_stop(exit_code, why, message, &info);
@@ -2836,8 +2842,8 @@ static int ptrace_signal(int signr, kernel_siginfo_t *info, enum pid_type type)
 		info->si_code = SI_USER;
 		rcu_read_lock();
 		info->si_pid = task_pid_vnr(current->parent);
-		info->si_uid = from_kuid_munged(current_user_ns(),
-						task_uid(current->parent));
+		siginfo_set_uid(info, current_user_ns(),
+				task_uid(current->parent));
 		rcu_read_unlock();
 	}
 
@@ -3639,6 +3645,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 	case SIL_KILL:
 		to->si_pid = from->si_pid;
 		to->si_uid = from->si_uid;
+		to->_sifields._sir._uid_r = from->si_uid_r;
 		break;
 	case SIL_TIMER:
 		to->si_tid     = from->si_tid;
@@ -3678,6 +3685,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 	case SIL_CHLD:
 		to->si_pid = from->si_pid;
 		to->si_uid = from->si_uid;
+		to->_sifields._sir._uid_r = from->si_uid_r;
 		to->si_status = from->si_status;
 		to->si_utime = from->si_utime;
 		to->si_stime = from->si_stime;
@@ -3685,6 +3693,7 @@ void copy_siginfo_to_external32(struct compat_siginfo *to,
 	case SIL_RT:
 		to->si_pid = from->si_pid;
 		to->si_uid = from->si_uid;
+		to->_sifields._sir._uid_r = from->si_uid_r;
 		to->si_int = from->si_int;
 		break;
 	case SIL_SYS:
@@ -3717,6 +3726,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 	case SIL_KILL:
 		to->si_pid = from->si_pid;
 		to->si_uid = from->si_uid;
+		to->si_uid_r = from->_sifields._sir._uid_r;
 		break;
 	case SIL_TIMER:
 		to->si_tid     = from->si_tid;
@@ -3756,6 +3766,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 	case SIL_CHLD:
 		to->si_pid    = from->si_pid;
 		to->si_uid    = from->si_uid;
+		to->si_uid_r  = from->_sifields._sir._uid_r;
 		to->si_status = from->si_status;
 #ifdef CONFIG_X86_X32_ABI
 		if (in_x32_syscall()) {
@@ -3771,6 +3782,7 @@ static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
 	case SIL_RT:
 		to->si_pid = from->si_pid;
 		to->si_uid = from->si_uid;
+		to->si_uid_r = from->_sifields._sir._uid_r;
 		to->si_int = from->si_int;
 		break;
 	case SIL_SYS:
@@ -4008,7 +4020,7 @@ static void prepare_kill_siginfo(int sig, struct kernel_siginfo *info,
 	info->si_errno = 0;
 	info->si_code = (type == PIDTYPE_PID) ? SI_TKILL : SI_USER;
 	info->si_pid = task_tgid_vnr(current);
-	info->si_uid = from_kuid_munged(current_user_ns(), current_uid());
+	siginfo_set_uid(info, current_user_ns(), current_uid());
 }
 
 /*
@@ -4979,6 +4991,12 @@ static inline void siginfo_buildtime_checks(void)
 	/* kill */
 	CHECK_OFFSET(si_pid);
 	CHECK_OFFSET(si_uid);
+	CHECK_OFFSET(si_uid_r);
+	BUILD_BUG_ON(offsetof(siginfo_t, si_uid_r) != __SI_UID_R_OFFSET);
+#ifdef CONFIG_COMPAT
+	BUILD_BUG_ON(offsetof(struct compat_siginfo, _sifields._sir._uid_r) !=
+		     __SI_UID_R_OFFSET);
+#endif
 
 	/* timer */
 	CHECK_OFFSET(si_tid);
-- 
2.56.0




More information about the Linux-security-module-archive mailing list