Skip to content

Commit

Permalink
move seccomp from /proc to a prctl
Browse files Browse the repository at this point in the history
This reduces the memory footprint and it enforces that only the current
task can enable seccomp on itself (this is a requirement for a
strightforward [modulo preempt ;) ] TIF_NOTSC implementation).

Signed-off-by: Andrea Arcangeli <andrea@cpushare.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Andrea Arcangeli authored and Linus Torvalds committed Jul 16, 2007
1 parent be0ef95 commit 1d9d02f
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 74 deletions.
72 changes: 0 additions & 72 deletions fs/proc/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
#include <linux/mount.h>
#include <linux/security.h>
#include <linux/ptrace.h>
#include <linux/seccomp.h>
#include <linux/cpuset.h>
#include <linux/audit.h>
#include <linux/poll.h>
Expand Down Expand Up @@ -817,71 +816,6 @@ static const struct file_operations proc_loginuid_operations = {
};
#endif

#ifdef CONFIG_SECCOMP
static ssize_t seccomp_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
char __buf[20];
size_t len;

if (!tsk)
return -ESRCH;
/* no need to print the trailing zero, so use only len */
len = sprintf(__buf, "%u\n", tsk->seccomp.mode);
put_task_struct(tsk);

return simple_read_from_buffer(buf, count, ppos, __buf, len);
}

static ssize_t seccomp_write(struct file *file, const char __user *buf,
size_t count, loff_t *ppos)
{
struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode);
char __buf[20], *end;
unsigned int seccomp_mode;
ssize_t result;

result = -ESRCH;
if (!tsk)
goto out_no_task;

/* can set it only once to be even more secure */
result = -EPERM;
if (unlikely(tsk->seccomp.mode))
goto out;

result = -EFAULT;
memset(__buf, 0, sizeof(__buf));
count = min(count, sizeof(__buf) - 1);
if (copy_from_user(__buf, buf, count))
goto out;

seccomp_mode = simple_strtoul(__buf, &end, 0);
if (*end == '\n')
end++;
result = -EINVAL;
if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
tsk->seccomp.mode = seccomp_mode;
set_tsk_thread_flag(tsk, TIF_SECCOMP);
} else
goto out;
result = -EIO;
if (unlikely(!(end - __buf)))
goto out;
result = end - __buf;
out:
put_task_struct(tsk);
out_no_task:
return result;
}

static const struct file_operations proc_seccomp_operations = {
.read = seccomp_read,
.write = seccomp_write,
};
#endif /* CONFIG_SECCOMP */

#ifdef CONFIG_FAULT_INJECTION
static ssize_t proc_fault_inject_read(struct file * file, char __user * buf,
size_t count, loff_t *ppos)
Expand Down Expand Up @@ -2042,9 +1976,6 @@ static const struct pid_entry tgid_base_stuff[] = {
REG("numa_maps", S_IRUGO, numa_maps),
#endif
REG("mem", S_IRUSR|S_IWUSR, mem),
#ifdef CONFIG_SECCOMP
REG("seccomp", S_IRUSR|S_IWUSR, seccomp),
#endif
LNK("cwd", cwd),
LNK("root", root),
LNK("exe", exe),
Expand Down Expand Up @@ -2329,9 +2260,6 @@ static const struct pid_entry tid_base_stuff[] = {
REG("numa_maps", S_IRUGO, numa_maps),
#endif
REG("mem", S_IRUSR|S_IWUSR, mem),
#ifdef CONFIG_SECCOMP
REG("seccomp", S_IRUSR|S_IWUSR, seccomp),
#endif
LNK("cwd", cwd),
LNK("root", root),
LNK("exe", exe),
Expand Down
4 changes: 4 additions & 0 deletions include/linux/prctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,8 @@
# define PR_ENDIAN_LITTLE 1 /* True little endian mode */
# define PR_ENDIAN_PPC_LITTLE 2 /* "PowerPC" pseudo little endian */

/* Get/set process seccomp mode */
#define PR_GET_SECCOMP 21
#define PR_SET_SECCOMP 22

#endif /* _LINUX_PRCTL_H */
15 changes: 13 additions & 2 deletions include/linux/seccomp.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

#ifdef CONFIG_SECCOMP

#define NR_SECCOMP_MODES 1

#include <linux/thread_info.h>
#include <asm/seccomp.h>

Expand All @@ -23,6 +21,9 @@ static inline int has_secure_computing(struct thread_info *ti)
return unlikely(test_ti_thread_flag(ti, TIF_SECCOMP));
}

extern long prctl_get_seccomp(void);
extern long prctl_set_seccomp(unsigned long);

#else /* CONFIG_SECCOMP */

typedef struct { } seccomp_t;
Expand All @@ -34,6 +35,16 @@ static inline int has_secure_computing(struct thread_info *ti)
return 0;
}

static inline long prctl_get_seccomp(void)
{
return -EINVAL;
}

static inline long prctl_set_seccomp(unsigned long arg2)
{
return -EINVAL;
}

#endif /* CONFIG_SECCOMP */

#endif /* _LINUX_SECCOMP_H */
26 changes: 26 additions & 0 deletions kernel/seccomp.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <linux/sched.h>

/* #define SECCOMP_DEBUG 1 */
#define NR_SECCOMP_MODES 1

/*
* Secure computing mode 1 allows only read/write/exit/sigreturn.
Expand Down Expand Up @@ -54,3 +55,28 @@ void __secure_computing(int this_syscall)
#endif
do_exit(SIGKILL);
}

long prctl_get_seccomp(void)
{
return current->seccomp.mode;
}

long prctl_set_seccomp(unsigned long seccomp_mode)
{
long ret;

/* can set it only once to be even more secure */
ret = -EPERM;
if (unlikely(current->seccomp.mode))
goto out;

ret = -EINVAL;
if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
current->seccomp.mode = seccomp_mode;
set_thread_flag(TIF_SECCOMP);
ret = 0;
}

out:
return ret;
}
8 changes: 8 additions & 0 deletions kernel/sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <linux/cn_proc.h>
#include <linux/getcpu.h>
#include <linux/task_io_accounting_ops.h>
#include <linux/seccomp.h>

#include <linux/compat.h>
#include <linux/syscalls.h>
Expand Down Expand Up @@ -2242,6 +2243,13 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
error = SET_ENDIAN(current, arg2);
break;

case PR_GET_SECCOMP:
error = prctl_get_seccomp();
break;
case PR_SET_SECCOMP:
error = prctl_set_seccomp(arg2);
break;

default:
error = -EINVAL;
break;
Expand Down

0 comments on commit 1d9d02f

Please sign in to comment.