Skip to content

Commit 7fc0350

Browse files
committed
Merge tag 'execve-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull execve updates from Kees Cook: "Most are small refactorings and bug fixes, but three things stand out: switching timens (which got reverted before) looks solid now, FOLL_FORCE has been removed (no failures seen yet across several weeks in -next), and some whitespace cleanups (which are long overdue). - Add timens support (when switching mm). This version has survived in -next for the entire cycle (Andrei Vagin) - Various small bug fixes, refactoring, and readability improvements (Bernd Edlinger, Rolf Eike Beer, Bo Liu, Li Zetao Liu Shixin) - Remove FOLL_FORCE for stack setup (Kees Cook) - Whitespace cleanups (Rolf Eike Beer, Kees Cook)" * tag 'execve-v6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: binfmt_misc: fix shift-out-of-bounds in check_special_flags binfmt: Fix error return code in load_elf_fdpic_binary() exec: Remove FOLL_FORCE for stack setup binfmt_elf: replace IS_ERR() with IS_ERR_VALUE() binfmt_elf: simplify error handling in load_elf_phdrs() binfmt_elf: fix documented return value for load_elf_phdrs() exec: simplify initial stack size expansion binfmt: Fix whitespace issues exec: Add comments on check_unsafe_exec() fs counting ELF uapi: add spaces before '{' selftests/timens: add a test for vfork+exit fs/exec: switch timens when a task gets a new mm
2 parents 667161b + 6a46bf5 commit 7fc0350

File tree

11 files changed

+215
-55
lines changed

11 files changed

+215
-55
lines changed

fs/binfmt_elf.c

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ create_elf_tables(struct linux_binprm *bprm, const struct elfhdr *exec,
248248
} while (0)
249249

250250
#ifdef ARCH_DLINFO
251-
/*
251+
/*
252252
* ARCH_DLINFO must come first so PPC can do its special alignment of
253253
* AUXV.
254254
* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT() in
@@ -456,13 +456,13 @@ static unsigned long maximum_alignment(struct elf_phdr *cmds, int nr)
456456
*
457457
* Loads ELF program headers from the binary file elf_file, which has the ELF
458458
* header pointed to by elf_ex, into a newly allocated array. The caller is
459-
* responsible for freeing the allocated data. Returns an ERR_PTR upon failure.
459+
* responsible for freeing the allocated data. Returns NULL upon failure.
460460
*/
461461
static struct elf_phdr *load_elf_phdrs(const struct elfhdr *elf_ex,
462462
struct file *elf_file)
463463
{
464464
struct elf_phdr *elf_phdata = NULL;
465-
int retval, err = -1;
465+
int retval = -1;
466466
unsigned int size;
467467

468468
/*
@@ -484,15 +484,9 @@ static struct elf_phdr *load_elf_phdrs(const struct elfhdr *elf_ex,
484484

485485
/* Read in the program headers */
486486
retval = elf_read(elf_file, elf_phdata, size, elf_ex->e_phoff);
487-
if (retval < 0) {
488-
err = retval;
489-
goto out;
490-
}
491487

492-
/* Success! */
493-
err = 0;
494488
out:
495-
if (err) {
489+
if (retval) {
496490
kfree(elf_phdata);
497491
elf_phdata = NULL;
498492
}
@@ -1020,7 +1014,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
10201014
executable_stack);
10211015
if (retval < 0)
10221016
goto out_free_dentry;
1023-
1017+
10241018
elf_bss = 0;
10251019
elf_brk = 0;
10261020

@@ -1043,7 +1037,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
10431037

10441038
if (unlikely (elf_brk > elf_bss)) {
10451039
unsigned long nbyte;
1046-
1040+
10471041
/* There was a PT_LOAD segment with p_memsz > p_filesz
10481042
before this one. Map anonymous pages, if needed,
10491043
and clear the area. */
@@ -1166,7 +1160,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
11661160
error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt,
11671161
elf_prot, elf_flags, total_size);
11681162
if (BAD_ADDR(error)) {
1169-
retval = IS_ERR((void *)error) ?
1163+
retval = IS_ERR_VALUE(error) ?
11701164
PTR_ERR((void*)error) : -EINVAL;
11711165
goto out_free_dentry;
11721166
}
@@ -1251,7 +1245,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
12511245
interpreter,
12521246
load_bias, interp_elf_phdata,
12531247
&arch_state);
1254-
if (!IS_ERR((void *)elf_entry)) {
1248+
if (!IS_ERR_VALUE(elf_entry)) {
12551249
/*
12561250
* load_elf_interp() returns relocation
12571251
* adjustment
@@ -1260,7 +1254,7 @@ static int load_elf_binary(struct linux_binprm *bprm)
12601254
elf_entry += interp_elf_ex->e_entry;
12611255
}
12621256
if (BAD_ADDR(elf_entry)) {
1263-
retval = IS_ERR((void *)elf_entry) ?
1257+
retval = IS_ERR_VALUE(elf_entry) ?
12641258
(int)elf_entry : -EINVAL;
12651259
goto out_free_dentry;
12661260
}
@@ -1521,7 +1515,7 @@ static void fill_elf_note_phdr(struct elf_phdr *phdr, int sz, loff_t offset)
15211515
phdr->p_align = 0;
15221516
}
15231517

1524-
static void fill_note(struct memelfnote *note, const char *name, int type,
1518+
static void fill_note(struct memelfnote *note, const char *name, int type,
15251519
unsigned int sz, void *data)
15261520
{
15271521
note->name = name;
@@ -2004,8 +1998,8 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t)
20041998
t->num_notes = 0;
20051999

20062000
fill_prstatus(&t->prstatus.common, p, signr);
2007-
elf_core_copy_task_regs(p, &t->prstatus.pr_reg);
2008-
2001+
elf_core_copy_task_regs(p, &t->prstatus.pr_reg);
2002+
20092003
fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus),
20102004
&(t->prstatus));
20112005
t->num_notes++;
@@ -2295,7 +2289,7 @@ static int elf_core_dump(struct coredump_params *cprm)
22952289
if (!elf_core_write_extra_phdrs(cprm, offset))
22962290
goto end_coredump;
22972291

2298-
/* write out the notes section */
2292+
/* write out the notes section */
22992293
if (!write_note_info(&info, cprm))
23002294
goto end_coredump;
23012295

fs/binfmt_elf_fdpic.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,9 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm)
434434
current->mm->start_stack = current->mm->start_brk + stack_size;
435435
#endif
436436

437-
if (create_elf_fdpic_tables(bprm, current->mm,
438-
&exec_params, &interp_params) < 0)
437+
retval = create_elf_fdpic_tables(bprm, current->mm, &exec_params,
438+
&interp_params);
439+
if (retval < 0)
439440
goto error;
440441

441442
kdebug("- start_code %lx", current->mm->start_code);
@@ -1603,7 +1604,7 @@ static int elf_fdpic_core_dump(struct coredump_params *cprm)
16031604
if (!elf_core_write_extra_phdrs(cprm, offset))
16041605
goto end_coredump;
16051606

1606-
/* write out the notes section */
1607+
/* write out the notes section */
16071608
if (!writenote(thread_list->notes, cprm))
16081609
goto end_coredump;
16091610
if (!writenote(&psinfo_note, cprm))

fs/binfmt_misc.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ static LIST_HEAD(entries);
4444
static int enabled = 1;
4545

4646
enum {Enabled, Magic};
47-
#define MISC_FMT_PRESERVE_ARGV0 (1 << 31)
48-
#define MISC_FMT_OPEN_BINARY (1 << 30)
49-
#define MISC_FMT_CREDENTIALS (1 << 29)
50-
#define MISC_FMT_OPEN_FILE (1 << 28)
47+
#define MISC_FMT_PRESERVE_ARGV0 (1UL << 31)
48+
#define MISC_FMT_OPEN_BINARY (1UL << 30)
49+
#define MISC_FMT_CREDENTIALS (1UL << 29)
50+
#define MISC_FMT_OPEN_FILE (1UL << 28)
5151

5252
typedef struct {
5353
struct list_head list;

fs/exec.c

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include <linux/io_uring.h>
6565
#include <linux/syscall_user_dispatch.h>
6666
#include <linux/coredump.h>
67+
#include <linux/time_namespace.h>
6768

6869
#include <linux/uaccess.h>
6970
#include <asm/mmu_context.h>
@@ -171,7 +172,7 @@ SYSCALL_DEFINE1(uselib, const char __user *, library)
171172
exit:
172173
fput(file);
173174
out:
174-
return error;
175+
return error;
175176
}
176177
#endif /* #ifdef CONFIG_USELIB */
177178

@@ -199,7 +200,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
199200
{
200201
struct page *page;
201202
int ret;
202-
unsigned int gup_flags = FOLL_FORCE;
203+
unsigned int gup_flags = 0;
203204

204205
#ifdef CONFIG_STACK_GROWSUP
205206
if (write) {
@@ -842,16 +843,13 @@ int setup_arg_pages(struct linux_binprm *bprm,
842843
* will align it up.
843844
*/
844845
rlim_stack = bprm->rlim_stack.rlim_cur & PAGE_MASK;
846+
847+
stack_expand = min(rlim_stack, stack_size + stack_expand);
848+
845849
#ifdef CONFIG_STACK_GROWSUP
846-
if (stack_size + stack_expand > rlim_stack)
847-
stack_base = vma->vm_start + rlim_stack;
848-
else
849-
stack_base = vma->vm_end + stack_expand;
850+
stack_base = vma->vm_start + stack_expand;
850851
#else
851-
if (stack_size + stack_expand > rlim_stack)
852-
stack_base = vma->vm_end - rlim_stack;
853-
else
854-
stack_base = vma->vm_start - stack_expand;
852+
stack_base = vma->vm_end - stack_expand;
855853
#endif
856854
current->mm->start_stack = bprm->p;
857855
ret = expand_stack(vma, stack_base);
@@ -1297,6 +1295,10 @@ int begin_new_exec(struct linux_binprm * bprm)
12971295

12981296
bprm->mm = NULL;
12991297

1298+
retval = exec_task_namespaces();
1299+
if (retval)
1300+
goto out_unlock;
1301+
13001302
#ifdef CONFIG_POSIX_TIMERS
13011303
spin_lock_irq(&me->sighand->siglock);
13021304
posix_cpu_timers_exit(me);
@@ -1568,6 +1570,12 @@ static void check_unsafe_exec(struct linux_binprm *bprm)
15681570
if (task_no_new_privs(current))
15691571
bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS;
15701572

1573+
/*
1574+
* If another task is sharing our fs, we cannot safely
1575+
* suid exec because the differently privileged task
1576+
* will be able to manipulate the current directory, etc.
1577+
* It would be nice to force an unshare instead...
1578+
*/
15711579
t = p;
15721580
n_fs = 1;
15731581
spin_lock(&p->fs->lock);
@@ -1748,6 +1756,7 @@ static int search_binary_handler(struct linux_binprm *bprm)
17481756
return retval;
17491757
}
17501758

1759+
/* binfmt handlers will call back into begin_new_exec() on success. */
17511760
static int exec_binprm(struct linux_binprm *bprm)
17521761
{
17531762
pid_t old_pid, old_vpid;
@@ -1806,6 +1815,11 @@ static int bprm_execve(struct linux_binprm *bprm,
18061815
if (retval)
18071816
return retval;
18081817

1818+
/*
1819+
* Check for unsafe execution states before exec_binprm(), which
1820+
* will call back into begin_new_exec(), into bprm_creds_from_file(),
1821+
* where setuid-ness is evaluated.
1822+
*/
18091823
check_unsafe_exec(bprm);
18101824
current->in_execve = 1;
18111825

include/linux/nsproxy.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ static inline struct cred *nsset_cred(struct nsset *set)
9494
int copy_namespaces(unsigned long flags, struct task_struct *tsk);
9595
void exit_task_namespaces(struct task_struct *tsk);
9696
void switch_task_namespaces(struct task_struct *tsk, struct nsproxy *new);
97+
int exec_task_namespaces(void);
9798
void free_nsproxy(struct nsproxy *ns);
9899
int unshare_nsproxy_namespaces(unsigned long, struct nsproxy **,
99100
struct cred *, struct fs_struct *);

include/uapi/linux/elf.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ typedef __s64 Elf64_Sxword;
9191
#define DT_INIT 12
9292
#define DT_FINI 13
9393
#define DT_SONAME 14
94-
#define DT_RPATH 15
94+
#define DT_RPATH 15
9595
#define DT_SYMBOLIC 16
9696
#define DT_REL 17
9797
#define DT_RELSZ 18
@@ -140,9 +140,9 @@ typedef __s64 Elf64_Sxword;
140140
#define ELF64_ST_BIND(x) ELF_ST_BIND(x)
141141
#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x)
142142

143-
typedef struct dynamic{
143+
typedef struct dynamic {
144144
Elf32_Sword d_tag;
145-
union{
145+
union {
146146
Elf32_Sword d_val;
147147
Elf32_Addr d_ptr;
148148
} d_un;
@@ -173,7 +173,7 @@ typedef struct elf64_rel {
173173
Elf64_Xword r_info; /* index and type of relocation */
174174
} Elf64_Rel;
175175

176-
typedef struct elf32_rela{
176+
typedef struct elf32_rela {
177177
Elf32_Addr r_offset;
178178
Elf32_Word r_info;
179179
Elf32_Sword r_addend;
@@ -185,7 +185,7 @@ typedef struct elf64_rela {
185185
Elf64_Sxword r_addend; /* Constant addend used to compute value */
186186
} Elf64_Rela;
187187

188-
typedef struct elf32_sym{
188+
typedef struct elf32_sym {
189189
Elf32_Word st_name;
190190
Elf32_Addr st_value;
191191
Elf32_Word st_size;
@@ -206,7 +206,7 @@ typedef struct elf64_sym {
206206

207207
#define EI_NIDENT 16
208208

209-
typedef struct elf32_hdr{
209+
typedef struct elf32_hdr {
210210
unsigned char e_ident[EI_NIDENT];
211211
Elf32_Half e_type;
212212
Elf32_Half e_machine;
@@ -246,7 +246,7 @@ typedef struct elf64_hdr {
246246
#define PF_W 0x2
247247
#define PF_X 0x1
248248

249-
typedef struct elf32_phdr{
249+
typedef struct elf32_phdr {
250250
Elf32_Word p_type;
251251
Elf32_Off p_offset;
252252
Elf32_Addr p_vaddr;

kernel/fork.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,15 +2046,6 @@ static __latent_entropy struct task_struct *copy_process(
20462046
return ERR_PTR(-EINVAL);
20472047
}
20482048

2049-
/*
2050-
* If the new process will be in a different time namespace
2051-
* do not allow it to share VM or a thread group with the forking task.
2052-
*/
2053-
if (clone_flags & (CLONE_THREAD | CLONE_VM)) {
2054-
if (nsp->time_ns != nsp->time_ns_for_children)
2055-
return ERR_PTR(-EINVAL);
2056-
}
2057-
20582049
if (clone_flags & CLONE_PIDFD) {
20592050
/*
20602051
* - CLONE_DETACHED is blocked so that we can potentially

kernel/nsproxy.c

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
157157
if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
158158
CLONE_NEWPID | CLONE_NEWNET |
159159
CLONE_NEWCGROUP | CLONE_NEWTIME)))) {
160-
if (likely(old_ns->time_ns_for_children == old_ns->time_ns)) {
160+
if ((flags & CLONE_VM) ||
161+
likely(old_ns->time_ns_for_children == old_ns->time_ns)) {
161162
get_nsproxy(old_ns);
162163
return 0;
163164
}
@@ -179,7 +180,8 @@ int copy_namespaces(unsigned long flags, struct task_struct *tsk)
179180
if (IS_ERR(new_ns))
180181
return PTR_ERR(new_ns);
181182

182-
timens_on_fork(new_ns, tsk);
183+
if ((flags & CLONE_VM) == 0)
184+
timens_on_fork(new_ns, tsk);
183185

184186
tsk->nsproxy = new_ns;
185187
return 0;
@@ -254,6 +256,23 @@ void exit_task_namespaces(struct task_struct *p)
254256
switch_task_namespaces(p, NULL);
255257
}
256258

259+
int exec_task_namespaces(void)
260+
{
261+
struct task_struct *tsk = current;
262+
struct nsproxy *new;
263+
264+
if (tsk->nsproxy->time_ns_for_children == tsk->nsproxy->time_ns)
265+
return 0;
266+
267+
new = create_new_namespaces(0, tsk, current_user_ns(), tsk->fs);
268+
if (IS_ERR(new))
269+
return PTR_ERR(new);
270+
271+
timens_on_fork(new, tsk);
272+
switch_task_namespaces(tsk, new);
273+
return 0;
274+
}
275+
257276
static int check_setns_flags(unsigned long flags)
258277
{
259278
if (!flags || (flags & ~(CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |

tools/testing/selftests/timens/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ procfs
88
timens
99
timer
1010
timerfd
11+
vfork_exec

tools/testing/selftests/timens/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
TEST_GEN_PROGS := timens timerfd timer clock_nanosleep procfs exec futex
1+
TEST_GEN_PROGS := timens timerfd timer clock_nanosleep procfs exec futex vfork_exec
22
TEST_GEN_PROGS_EXTENDED := gettime_perf
33

44
CFLAGS := -Wall -Werror -pthread

0 commit comments

Comments
 (0)