Skip to content

Commit d471ce5

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml
Pull UML fixes from Richard Weinberger: "Special thanks goes to Toralf Föster for continuously testing UML and reporting issues!" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rw/uml: um: remove dead code um: siginfo cleanup uml: Fix which_tmpdir failure when /dev/shm is a symlink, and in other edge cases um: Fix wait_stub_done() error handling um: Mark stub pages mapping with VM_PFNMAP um: Fix return value of strnlen_user()
2 parents 1b05018 + 9e82d45 commit d471ce5

File tree

8 files changed

+213
-61
lines changed

8 files changed

+213
-61
lines changed

arch/um/include/shared/frame_kern.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
#ifndef __FRAME_KERN_H_
77
#define __FRAME_KERN_H_
88

9-
extern int setup_signal_stack_sc(unsigned long stack_top, int sig,
9+
extern int setup_signal_stack_sc(unsigned long stack_top, int sig,
1010
struct k_sigaction *ka,
11-
struct pt_regs *regs,
11+
struct pt_regs *regs,
1212
sigset_t *mask);
13-
extern int setup_signal_stack_si(unsigned long stack_top, int sig,
13+
extern int setup_signal_stack_si(unsigned long stack_top, int sig,
1414
struct k_sigaction *ka,
15-
struct pt_regs *regs, siginfo_t *info,
15+
struct pt_regs *regs, struct siginfo *info,
1616
sigset_t *mask);
1717

1818
#endif

arch/um/kernel/signal.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ EXPORT_SYMBOL(unblock_signals);
1919
* OK, we're invoking a handler
2020
*/
2121
static void handle_signal(struct pt_regs *regs, unsigned long signr,
22-
struct k_sigaction *ka, siginfo_t *info)
22+
struct k_sigaction *ka, struct siginfo *info)
2323
{
2424
sigset_t *oldset = sigmask_to_save();
2525
int singlestep = 0;
@@ -71,7 +71,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
7171
static int kern_do_signal(struct pt_regs *regs)
7272
{
7373
struct k_sigaction ka_copy;
74-
siginfo_t info;
74+
struct siginfo info;
7575
int sig, handled_sig = 0;
7676

7777
while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) {

arch/um/kernel/skas/mmu.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ void uml_setup_stubs(struct mm_struct *mm)
123123
/* dup_mmap already holds mmap_sem */
124124
err = install_special_mapping(mm, STUB_START, STUB_END - STUB_START,
125125
VM_READ | VM_MAYREAD | VM_EXEC |
126-
VM_MAYEXEC | VM_DONTCOPY,
126+
VM_MAYEXEC | VM_DONTCOPY | VM_PFNMAP,
127127
mm->context.stub_pages);
128128
if (err) {
129129
printk(KERN_ERR "install_special_mapping returned %d\n", err);

arch/um/kernel/skas/uaccess.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,6 @@ int strnlen_user(const void __user *str, int len)
254254
n = buffer_op((unsigned long) str, len, 0, strnlen_chunk, &count);
255255
if (n == 0)
256256
return count + 1;
257-
return -EFAULT;
257+
return 0;
258258
}
259259
EXPORT_SYMBOL(strnlen_user);

arch/um/os-Linux/mem.c

Lines changed: 189 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,25 @@ static void __init find_tempdir(void)
5252
strcat(tempdir, "/");
5353
}
5454

55+
/*
56+
* Remove bytes from the front of the buffer and refill it so that if there's a
57+
* partial string that we care about, it will be completed, and we can recognize
58+
* it.
59+
*/
60+
static int pop(int fd, char *buf, size_t size, size_t npop)
61+
{
62+
ssize_t n;
63+
size_t len = strlen(&buf[npop]);
64+
65+
memmove(buf, &buf[npop], len + 1);
66+
n = read(fd, &buf[len], size - len - 1);
67+
if (n < 0)
68+
return -errno;
69+
70+
buf[len + n] = '\0';
71+
return 1;
72+
}
73+
5574
/*
5675
* This will return 1, with the first character in buf being the
5776
* character following the next instance of c in the file. This will
@@ -61,7 +80,6 @@ static void __init find_tempdir(void)
6180
static int next(int fd, char *buf, size_t size, char c)
6281
{
6382
ssize_t n;
64-
size_t len;
6583
char *ptr;
6684

6785
while ((ptr = strchr(buf, c)) == NULL) {
@@ -74,20 +92,129 @@ static int next(int fd, char *buf, size_t size, char c)
7492
buf[n] = '\0';
7593
}
7694

77-
ptr++;
78-
len = strlen(ptr);
79-
memmove(buf, ptr, len + 1);
95+
return pop(fd, buf, size, ptr - buf + 1);
96+
}
97+
98+
/*
99+
* Decode an octal-escaped and space-terminated path of the form used by
100+
* /proc/mounts. May be used to decode a path in-place. "out" must be at least
101+
* as large as the input. The output is always null-terminated. "len" gets the
102+
* length of the output, excluding the trailing null. Returns 0 if a full path
103+
* was successfully decoded, otherwise an error.
104+
*/
105+
static int decode_path(const char *in, char *out, size_t *len)
106+
{
107+
char *first = out;
108+
int c;
109+
int i;
110+
int ret = -EINVAL;
111+
while (1) {
112+
switch (*in) {
113+
case '\0':
114+
goto out;
115+
116+
case ' ':
117+
ret = 0;
118+
goto out;
119+
120+
case '\\':
121+
in++;
122+
c = 0;
123+
for (i = 0; i < 3; i++) {
124+
if (*in < '0' || *in > '7')
125+
goto out;
126+
c = (c << 3) | (*in++ - '0');
127+
}
128+
*(unsigned char *)out++ = (unsigned char) c;
129+
break;
130+
131+
default:
132+
*out++ = *in++;
133+
break;
134+
}
135+
}
136+
137+
out:
138+
*out = '\0';
139+
*len = out - first;
140+
return ret;
141+
}
142+
143+
/*
144+
* Computes the length of s when encoded with three-digit octal escape sequences
145+
* for the characters in chars.
146+
*/
147+
static size_t octal_encoded_length(const char *s, const char *chars)
148+
{
149+
size_t len = strlen(s);
150+
while ((s = strpbrk(s, chars)) != NULL) {
151+
len += 3;
152+
s++;
153+
}
154+
155+
return len;
156+
}
157+
158+
enum {
159+
OUTCOME_NOTHING_MOUNTED,
160+
OUTCOME_TMPFS_MOUNT,
161+
OUTCOME_NON_TMPFS_MOUNT,
162+
};
163+
164+
/* Read a line of /proc/mounts data looking for a tmpfs mount at "path". */
165+
static int read_mount(int fd, char *buf, size_t bufsize, const char *path,
166+
int *outcome)
167+
{
168+
int found;
169+
int match;
170+
char *space;
171+
size_t len;
172+
173+
enum {
174+
MATCH_NONE,
175+
MATCH_EXACT,
176+
MATCH_PARENT,
177+
};
178+
179+
found = next(fd, buf, bufsize, ' ');
180+
if (found != 1)
181+
return found;
80182

81183
/*
82-
* Refill the buffer so that if there's a partial string that we care
83-
* about, it will be completed, and we can recognize it.
184+
* If there's no following space in the buffer, then this path is
185+
* truncated, so it can't be the one we're looking for.
84186
*/
85-
n = read(fd, &buf[len], size - len - 1);
86-
if (n < 0)
87-
return -errno;
187+
space = strchr(buf, ' ');
188+
if (space) {
189+
match = MATCH_NONE;
190+
if (!decode_path(buf, buf, &len)) {
191+
if (!strcmp(buf, path))
192+
match = MATCH_EXACT;
193+
else if (!strncmp(buf, path, len)
194+
&& (path[len] == '/' || !strcmp(buf, "/")))
195+
match = MATCH_PARENT;
196+
}
197+
198+
found = pop(fd, buf, bufsize, space - buf + 1);
199+
if (found != 1)
200+
return found;
201+
202+
switch (match) {
203+
case MATCH_EXACT:
204+
if (!strncmp(buf, "tmpfs", strlen("tmpfs")))
205+
*outcome = OUTCOME_TMPFS_MOUNT;
206+
else
207+
*outcome = OUTCOME_NON_TMPFS_MOUNT;
208+
break;
88209

89-
buf[len + n] = '\0';
90-
return 1;
210+
case MATCH_PARENT:
211+
/* This mount obscures any previous ones. */
212+
*outcome = OUTCOME_NOTHING_MOUNTED;
213+
break;
214+
}
215+
}
216+
217+
return next(fd, buf, bufsize, '\n');
91218
}
92219

93220
/* which_tmpdir is called only during early boot */
@@ -106,8 +233,12 @@ static int checked_tmpdir = 0;
106233
*/
107234
static void which_tmpdir(void)
108235
{
109-
int fd, found;
110-
char buf[128] = { '\0' };
236+
int fd;
237+
int found;
238+
int outcome;
239+
char *path;
240+
char *buf;
241+
size_t bufsize;
111242

112243
if (checked_tmpdir)
113244
return;
@@ -116,49 +247,66 @@ static void which_tmpdir(void)
116247

117248
printf("Checking for tmpfs mount on /dev/shm...");
118249

250+
path = realpath("/dev/shm", NULL);
251+
if (!path) {
252+
printf("failed to check real path, errno = %d\n", errno);
253+
return;
254+
}
255+
printf("%s...", path);
256+
257+
/*
258+
* The buffer needs to be able to fit the full octal-escaped path, a
259+
* space, and a trailing null in order to successfully decode it.
260+
*/
261+
bufsize = octal_encoded_length(path, " \t\n\\") + 2;
262+
263+
if (bufsize < 128)
264+
bufsize = 128;
265+
266+
buf = malloc(bufsize);
267+
if (!buf) {
268+
printf("malloc failed, errno = %d\n", errno);
269+
goto out;
270+
}
271+
buf[0] = '\0';
272+
119273
fd = open("/proc/mounts", O_RDONLY);
120274
if (fd < 0) {
121275
printf("failed to open /proc/mounts, errno = %d\n", errno);
122-
return;
276+
goto out1;
123277
}
124278

279+
outcome = OUTCOME_NOTHING_MOUNTED;
125280
while (1) {
126-
found = next(fd, buf, ARRAY_SIZE(buf), ' ');
127-
if (found != 1)
128-
break;
129-
130-
if (!strncmp(buf, "/dev/shm", strlen("/dev/shm")))
131-
goto found;
132-
133-
found = next(fd, buf, ARRAY_SIZE(buf), '\n');
281+
found = read_mount(fd, buf, bufsize, path, &outcome);
134282
if (found != 1)
135283
break;
136284
}
137285

138-
err:
139-
if (found == 0)
140-
printf("nothing mounted on /dev/shm\n");
141-
else if (found < 0)
286+
if (found < 0) {
142287
printf("read returned errno %d\n", -found);
288+
} else {
289+
switch (outcome) {
290+
case OUTCOME_TMPFS_MOUNT:
291+
printf("OK\n");
292+
default_tmpdir = "/dev/shm";
293+
break;
143294

144-
out:
145-
close(fd);
146-
147-
return;
148-
149-
found:
150-
found = next(fd, buf, ARRAY_SIZE(buf), ' ');
151-
if (found != 1)
152-
goto err;
295+
case OUTCOME_NON_TMPFS_MOUNT:
296+
printf("not tmpfs\n");
297+
break;
153298

154-
if (strncmp(buf, "tmpfs", strlen("tmpfs"))) {
155-
printf("not tmpfs\n");
156-
goto out;
299+
default:
300+
printf("nothing mounted on /dev/shm\n");
301+
break;
302+
}
157303
}
158304

159-
printf("OK\n");
160-
default_tmpdir = "/dev/shm";
161-
goto out;
305+
close(fd);
306+
out1:
307+
free(buf);
308+
out:
309+
free(path);
162310
}
163311

164312
static int __init make_tempfile(const char *template, char **out_tempname,

arch/um/os-Linux/signal.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
2525
[SIGIO] = sigio_handler,
2626
[SIGVTALRM] = timer_handler };
2727

28-
static void sig_handler_common(int sig, siginfo_t *si, mcontext_t *mc)
28+
static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
2929
{
3030
struct uml_pt_regs r;
3131
int save_errno = errno;
@@ -61,7 +61,7 @@ static void sig_handler_common(int sig, siginfo_t *si, mcontext_t *mc)
6161
static int signals_enabled;
6262
static unsigned int signals_pending;
6363

64-
void sig_handler(int sig, siginfo_t *si, mcontext_t *mc)
64+
void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
6565
{
6666
int enabled;
6767

@@ -120,7 +120,7 @@ void set_sigstack(void *sig_stack, int size)
120120
panic("enabling signal stack failed, errno = %d\n", errno);
121121
}
122122

123-
static void (*handlers[_NSIG])(int sig, siginfo_t *si, mcontext_t *mc) = {
123+
static void (*handlers[_NSIG])(int sig, struct siginfo *si, mcontext_t *mc) = {
124124
[SIGSEGV] = sig_handler,
125125
[SIGBUS] = sig_handler,
126126
[SIGILL] = sig_handler,
@@ -162,7 +162,7 @@ static void hard_handler(int sig, siginfo_t *si, void *p)
162162
while ((sig = ffs(pending)) != 0){
163163
sig--;
164164
pending &= ~(1 << sig);
165-
(*handlers[sig])(sig, si, mc);
165+
(*handlers[sig])(sig, (struct siginfo *)si, mc);
166166
}
167167

168168
/*

0 commit comments

Comments
 (0)