diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2018-09-25 12:27:20 +0300 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2018-10-03 17:47:43 +0300 |
commit | ae7795bc6187a15ec51cf258abae656a625f9980 (patch) | |
tree | 2456aa85c6b4be1ac58e272393056c0edbee038a /include | |
parent | 4cd2e0e70af6897ca2247fa1ffb1553ca16b4903 (diff) | |
download | linux-ae7795bc6187a15ec51cf258abae656a625f9980.tar.xz |
signal: Distinguish between kernel_siginfo and siginfo
Linus recently observed that if we did not worry about the padding
member in struct siginfo it is only about 48 bytes, and 48 bytes is
much nicer than 128 bytes for allocating on the stack and copying
around in the kernel.
The obvious thing of only adding the padding when userspace is
including siginfo.h won't work as there are sigframe definitions in
the kernel that embed struct siginfo.
So split siginfo in two; kernel_siginfo and siginfo. Keeping the
traditional name for the userspace definition. While the version that
is used internally to the kernel and ultimately will not be padded to
128 bytes is called kernel_siginfo.
The definition of struct kernel_siginfo I have put in include/signal_types.h
A set of buildtime checks has been added to verify the two structures have
the same field offsets.
To make it easy to verify the change kernel_siginfo retains the same
size as siginfo. The reduction in size comes in a following change.
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/binfmts.h | 2 | ||||
-rw-r--r-- | include/linux/compat.h | 4 | ||||
-rw-r--r-- | include/linux/coredump.h | 4 | ||||
-rw-r--r-- | include/linux/lsm_hooks.h | 4 | ||||
-rw-r--r-- | include/linux/posix-timers.h | 2 | ||||
-rw-r--r-- | include/linux/ptrace.h | 2 | ||||
-rw-r--r-- | include/linux/sched.h | 2 | ||||
-rw-r--r-- | include/linux/sched/signal.h | 18 | ||||
-rw-r--r-- | include/linux/security.h | 6 | ||||
-rw-r--r-- | include/linux/signal.h | 15 | ||||
-rw-r--r-- | include/linux/signal_types.h | 11 | ||||
-rw-r--r-- | include/trace/events/signal.h | 4 |
12 files changed, 41 insertions, 33 deletions
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index c05f24fac4f6..e9f5fe69df31 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h @@ -78,7 +78,7 @@ struct linux_binprm { /* Function parameter for binfmt->coredump */ struct coredump_params { - const siginfo_t *siginfo; + const kernel_siginfo_t *siginfo; struct pt_regs *regs; struct file *file; unsigned long limit; diff --git a/include/linux/compat.h b/include/linux/compat.h index 1a3c4f37e908..4565d65b1776 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -452,8 +452,8 @@ long compat_get_bitmap(unsigned long *mask, const compat_ulong_t __user *umask, unsigned long bitmap_size); long compat_put_bitmap(compat_ulong_t __user *umask, unsigned long *mask, unsigned long bitmap_size); -int copy_siginfo_from_user32(siginfo_t *to, const struct compat_siginfo __user *from); -int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *from); +int copy_siginfo_from_user32(kernel_siginfo_t *to, const struct compat_siginfo __user *from); +int copy_siginfo_to_user32(struct compat_siginfo __user *to, const kernel_siginfo_t *from); int get_compat_sigevent(struct sigevent *event, const struct compat_sigevent __user *u_event); diff --git a/include/linux/coredump.h b/include/linux/coredump.h index 207aed96a5b7..abf4b4e65dbb 100644 --- a/include/linux/coredump.h +++ b/include/linux/coredump.h @@ -17,9 +17,9 @@ extern int dump_emit(struct coredump_params *cprm, const void *addr, int nr); extern int dump_align(struct coredump_params *cprm, int align); extern void dump_truncate(struct coredump_params *cprm); #ifdef CONFIG_COREDUMP -extern void do_coredump(const siginfo_t *siginfo); +extern void do_coredump(const kernel_siginfo_t *siginfo); #else -static inline void do_coredump(const siginfo_t *siginfo) {} +static inline void do_coredump(const kernel_siginfo_t *siginfo) {} #endif #endif /* _LINUX_COREDUMP_H */ diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 97a020c616ad..bb40f6d34163 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -672,7 +672,7 @@ * Return 0 if permission is granted. * @task_kill: * Check permission before sending signal @sig to @p. @info can be NULL, - * the constant 1, or a pointer to a siginfo structure. If @info is 1 or + * the constant 1, or a pointer to a kernel_siginfo structure. If @info is 1 or * SI_FROMKERNEL(info) is true, then the signal should be viewed as coming * from the kernel and should typically be permitted. * SIGIO signals are handled separately by the send_sigiotask hook in @@ -1606,7 +1606,7 @@ union security_list_options { int (*task_setscheduler)(struct task_struct *p); int (*task_getscheduler)(struct task_struct *p); int (*task_movememory)(struct task_struct *p); - int (*task_kill)(struct task_struct *p, struct siginfo *info, + int (*task_kill)(struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred); int (*task_prctl)(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5); diff --git a/include/linux/posix-timers.h b/include/linux/posix-timers.h index ee7e987ea1b4..e96581ca7c9d 100644 --- a/include/linux/posix-timers.h +++ b/include/linux/posix-timers.h @@ -126,5 +126,5 @@ void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx, void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new); -void posixtimer_rearm(struct siginfo *info); +void posixtimer_rearm(struct kernel_siginfo *info); #endif diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 1de2235511c8..d19a795100da 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -341,7 +341,7 @@ extern void user_single_step_report(struct pt_regs *regs); #else static inline void user_single_step_report(struct pt_regs *regs) { - siginfo_t info; + kernel_siginfo_t info; clear_siginfo(&info); info.si_signo = SIGTRAP; info.si_errno = 0; diff --git a/include/linux/sched.h b/include/linux/sched.h index 977cb57d7bc9..2ba88082e1ef 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -960,7 +960,7 @@ struct task_struct { /* Ptrace state: */ unsigned long ptrace_message; - siginfo_t *last_siginfo; + kernel_siginfo_t *last_siginfo; struct task_io_accounting ioac; #ifdef CONFIG_TASK_XACCT diff --git a/include/linux/sched/signal.h b/include/linux/sched/signal.h index 9e07f3521549..13789d10a50e 100644 --- a/include/linux/sched/signal.h +++ b/include/linux/sched/signal.h @@ -270,12 +270,12 @@ static inline int signal_group_exit(const struct signal_struct *sig) extern void flush_signals(struct task_struct *); extern void ignore_signals(struct task_struct *); extern void flush_signal_handlers(struct task_struct *, int force_default); -extern int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info); +extern int dequeue_signal(struct task_struct *tsk, sigset_t *mask, kernel_siginfo_t *info); static inline int kernel_dequeue_signal(void) { struct task_struct *tsk = current; - siginfo_t __info; + kernel_siginfo_t __info; int ret; spin_lock_irq(&tsk->sighand->siglock); @@ -322,12 +322,12 @@ int force_sig_pkuerr(void __user *addr, u32 pkey); int force_sig_ptrace_errno_trap(int errno, void __user *addr); -extern int send_sig_info(int, struct siginfo *, struct task_struct *); +extern int send_sig_info(int, struct kernel_siginfo *, struct task_struct *); extern void force_sigsegv(int sig, struct task_struct *p); -extern int force_sig_info(int, struct siginfo *, struct task_struct *); -extern int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp); -extern int kill_pid_info(int sig, struct siginfo *info, struct pid *pid); -extern int kill_pid_info_as_cred(int, struct siginfo *, struct pid *, +extern int force_sig_info(int, struct kernel_siginfo *, struct task_struct *); +extern int __kill_pgrp_info(int sig, struct kernel_siginfo *info, struct pid *pgrp); +extern int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid); +extern int kill_pid_info_as_cred(int, struct kernel_siginfo *, struct pid *, const struct cred *); extern int kill_pgrp(struct pid *pid, int sig, int priv); extern int kill_pid(struct pid *pid, int sig, int priv); @@ -475,8 +475,8 @@ static inline int kill_cad_pid(int sig, int priv) } /* These can be the second arg to send_sig_info/send_group_sig_info. */ -#define SEND_SIG_NOINFO ((struct siginfo *) 0) -#define SEND_SIG_PRIV ((struct siginfo *) 1) +#define SEND_SIG_NOINFO ((struct kernel_siginfo *) 0) +#define SEND_SIG_PRIV ((struct kernel_siginfo *) 1) /* * True if we are on the alternate signal stack. diff --git a/include/linux/security.h b/include/linux/security.h index 75f4156c84d7..d170a5b031f3 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -35,7 +35,7 @@ struct linux_binprm; struct cred; struct rlimit; -struct siginfo; +struct kernel_siginfo; struct sembuf; struct kern_ipc_perm; struct audit_context; @@ -361,7 +361,7 @@ int security_task_setrlimit(struct task_struct *p, unsigned int resource, int security_task_setscheduler(struct task_struct *p); int security_task_getscheduler(struct task_struct *p); int security_task_movememory(struct task_struct *p); -int security_task_kill(struct task_struct *p, struct siginfo *info, +int security_task_kill(struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred); int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5); @@ -1020,7 +1020,7 @@ static inline int security_task_movememory(struct task_struct *p) } static inline int security_task_kill(struct task_struct *p, - struct siginfo *info, int sig, + struct kernel_siginfo *info, int sig, const struct cred *cred) { return 0; diff --git a/include/linux/signal.h b/include/linux/signal.h index de94c159bfb0..70031b10b918 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -11,18 +11,19 @@ struct task_struct; /* for sysctl */ extern int print_fatal_signals; -static inline void copy_siginfo(struct siginfo *to, const struct siginfo *from) +static inline void copy_siginfo(kernel_siginfo_t *to, + const kernel_siginfo_t *from) { memcpy(to, from, sizeof(*to)); } -static inline void clear_siginfo(struct siginfo *info) +static inline void clear_siginfo(kernel_siginfo_t *info) { memset(info, 0, sizeof(*info)); } -int copy_siginfo_to_user(struct siginfo __user *to, const struct siginfo *from); -int copy_siginfo_from_user(struct siginfo *to, const struct siginfo __user *from); +int copy_siginfo_to_user(siginfo_t __user *to, const kernel_siginfo_t *from); +int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from); enum siginfo_layout { SIL_KILL, @@ -258,11 +259,11 @@ struct pt_regs; enum pid_type; extern int next_signal(struct sigpending *pending, sigset_t *mask); -extern int do_send_sig_info(int sig, struct siginfo *info, +extern int do_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p, enum pid_type type); -extern int group_send_sig_info(int sig, struct siginfo *info, +extern int group_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p, enum pid_type type); -extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *); +extern int __group_send_sig_info(int, struct kernel_siginfo *, struct task_struct *); extern int sigprocmask(int, sigset_t *, sigset_t *); extern void set_current_blocked(sigset_t *); extern void __set_current_blocked(const sigset_t *); diff --git a/include/linux/signal_types.h b/include/linux/signal_types.h index 222ae696000b..2a40a9c5e4ad 100644 --- a/include/linux/signal_types.h +++ b/include/linux/signal_types.h @@ -9,6 +9,13 @@ #include <linux/list.h> #include <uapi/linux/signal.h> +typedef struct kernel_siginfo { + union { + __SIGINFO; + int _si_pad[SI_MAX_SIZE/sizeof(int)]; + }; +} kernel_siginfo_t; + /* * Real Time signals may be queued. */ @@ -16,7 +23,7 @@ struct sigqueue { struct list_head list; int flags; - siginfo_t info; + kernel_siginfo_t info; struct user_struct *user; }; @@ -60,7 +67,7 @@ struct old_sigaction { struct ksignal { struct k_sigaction ka; - siginfo_t info; + kernel_siginfo_t info; int sig; }; diff --git a/include/trace/events/signal.h b/include/trace/events/signal.h index 3deeed50ffd0..1db7e4b07c01 100644 --- a/include/trace/events/signal.h +++ b/include/trace/events/signal.h @@ -49,7 +49,7 @@ enum { */ TRACE_EVENT(signal_generate, - TP_PROTO(int sig, struct siginfo *info, struct task_struct *task, + TP_PROTO(int sig, struct kernel_siginfo *info, struct task_struct *task, int group, int result), TP_ARGS(sig, info, task, group, result), @@ -95,7 +95,7 @@ TRACE_EVENT(signal_generate, */ TRACE_EVENT(signal_deliver, - TP_PROTO(int sig, struct siginfo *info, struct k_sigaction *ka), + TP_PROTO(int sig, struct kernel_siginfo *info, struct k_sigaction *ka), TP_ARGS(sig, info, ka), |