Skip to content

Commit b0cfcdd

Browse files
committed
d_path: make 'prepend()' fill up the buffer exactly on overflow
Instead of just marking the buffer as having overflowed, fill it up as much as we can. That will allow the overflow case to then return whatever truncated result if it wants to. Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 7661809 commit b0cfcdd

1 file changed

Lines changed: 63 additions & 30 deletions

File tree

fs/d_path.c

Lines changed: 63 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,57 @@ static char *extract_string(struct prepend_buffer *p)
2222
return ERR_PTR(-ENAMETOOLONG);
2323
}
2424

25-
static void prepend(struct prepend_buffer *p, const char *str, int namelen)
25+
static bool prepend_char(struct prepend_buffer *p, unsigned char c)
2626
{
27-
p->len -= namelen;
28-
if (likely(p->len >= 0)) {
29-
p->buf -= namelen;
30-
memcpy(p->buf, str, namelen);
27+
if (likely(p->len > 0)) {
28+
p->len--;
29+
*--p->buf = c;
30+
return true;
31+
}
32+
p->len = -1;
33+
return false;
34+
}
35+
36+
/*
37+
* The source of the prepend data can be an optimistoc load
38+
* of a dentry name and length. And because we don't hold any
39+
* locks, the length and the pointer to the name may not be
40+
* in sync if a concurrent rename happens, and the kernel
41+
* copy might fault as a result.
42+
*
43+
* The end result will correct itself when we check the
44+
* rename sequence count, but we need to be able to handle
45+
* the fault gracefully.
46+
*/
47+
static bool prepend_copy(void *dst, const void *src, int len)
48+
{
49+
if (unlikely(copy_from_kernel_nofault(dst, src, len))) {
50+
memset(dst, 'x', len);
51+
return false;
3152
}
53+
return true;
54+
}
55+
56+
static bool prepend(struct prepend_buffer *p, const char *str, int namelen)
57+
{
58+
// Already overflowed?
59+
if (p->len < 0)
60+
return false;
61+
62+
// Will overflow?
63+
if (p->len < namelen) {
64+
// Fill as much as possible from the end of the name
65+
str += namelen - p->len;
66+
p->buf -= p->len;
67+
prepend_copy(p->buf, str, p->len);
68+
p->len = -1;
69+
return false;
70+
}
71+
72+
// Fits fully
73+
p->len -= namelen;
74+
p->buf -= namelen;
75+
return prepend_copy(p->buf, str, namelen);
3276
}
3377

3478
/**
@@ -40,32 +84,21 @@ static void prepend(struct prepend_buffer *p, const char *str, int namelen)
4084
* With RCU path tracing, it may race with d_move(). Use READ_ONCE() to
4185
* make sure that either the old or the new name pointer and length are
4286
* fetched. However, there may be mismatch between length and pointer.
43-
* The length cannot be trusted, we need to copy it byte-by-byte until
44-
* the length is reached or a null byte is found. It also prepends "/" at
87+
* But since the length cannot be trusted, we need to copy the name very
88+
* carefully when doing the prepend_copy(). It also prepends "/" at
4589
* the beginning of the name. The sequence number check at the caller will
4690
* retry it again when a d_move() does happen. So any garbage in the buffer
4791
* due to mismatched pointer and length will be discarded.
4892
*
49-
* Load acquire is needed to make sure that we see that terminating NUL.
93+
* Load acquire is needed to make sure that we see the new name data even
94+
* if we might get the length wrong.
5095
*/
5196
static bool prepend_name(struct prepend_buffer *p, const struct qstr *name)
5297
{
5398
const char *dname = smp_load_acquire(&name->name); /* ^^^ */
5499
u32 dlen = READ_ONCE(name->len);
55-
char *s;
56100

57-
p->len -= dlen + 1;
58-
if (unlikely(p->len < 0))
59-
return false;
60-
s = p->buf -= dlen + 1;
61-
*s++ = '/';
62-
while (dlen--) {
63-
char c = *dname++;
64-
if (!c)
65-
break;
66-
*s++ = c;
67-
}
68-
return true;
101+
return prepend(p, dname, dlen) && prepend_char(p, '/');
69102
}
70103

71104
static int __prepend_path(const struct dentry *dentry, const struct mount *mnt,
@@ -158,7 +191,7 @@ static int prepend_path(const struct path *path,
158191
b = *p;
159192

160193
if (b.len == p->len)
161-
prepend(&b, "/", 1);
194+
prepend_char(&b, '/');
162195

163196
*p = b;
164197
return error;
@@ -186,7 +219,7 @@ char *__d_path(const struct path *path,
186219
{
187220
DECLARE_BUFFER(b, buf, buflen);
188221

189-
prepend(&b, "", 1);
222+
prepend_char(&b, 0);
190223
if (unlikely(prepend_path(path, root, &b) > 0))
191224
return NULL;
192225
return extract_string(&b);
@@ -198,7 +231,7 @@ char *d_absolute_path(const struct path *path,
198231
struct path root = {};
199232
DECLARE_BUFFER(b, buf, buflen);
200233

201-
prepend(&b, "", 1);
234+
prepend_char(&b, 0);
202235
if (unlikely(prepend_path(path, &root, &b) > 1))
203236
return ERR_PTR(-EINVAL);
204237
return extract_string(&b);
@@ -255,7 +288,7 @@ char *d_path(const struct path *path, char *buf, int buflen)
255288
if (unlikely(d_unlinked(path->dentry)))
256289
prepend(&b, " (deleted)", 11);
257290
else
258-
prepend(&b, "", 1);
291+
prepend_char(&b, 0);
259292
prepend_path(path, &root, &b);
260293
rcu_read_unlock();
261294

@@ -290,7 +323,7 @@ char *simple_dname(struct dentry *dentry, char *buffer, int buflen)
290323
/* these dentries are never renamed, so d_lock is not needed */
291324
prepend(&b, " (deleted)", 11);
292325
prepend(&b, dentry->d_name.name, dentry->d_name.len);
293-
prepend(&b, "/", 1);
326+
prepend_char(&b, '/');
294327
return extract_string(&b);
295328
}
296329

@@ -324,15 +357,15 @@ static char *__dentry_path(const struct dentry *d, struct prepend_buffer *p)
324357
}
325358
done_seqretry(&rename_lock, seq);
326359
if (b.len == p->len)
327-
prepend(&b, "/", 1);
360+
prepend_char(&b, '/');
328361
return extract_string(&b);
329362
}
330363

331364
char *dentry_path_raw(const struct dentry *dentry, char *buf, int buflen)
332365
{
333366
DECLARE_BUFFER(b, buf, buflen);
334367

335-
prepend(&b, "", 1);
368+
prepend_char(&b, 0);
336369
return __dentry_path(dentry, &b);
337370
}
338371
EXPORT_SYMBOL(dentry_path_raw);
@@ -344,7 +377,7 @@ char *dentry_path(const struct dentry *dentry, char *buf, int buflen)
344377
if (unlikely(d_unlinked(dentry)))
345378
prepend(&b, "//deleted", 10);
346379
else
347-
prepend(&b, "", 1);
380+
prepend_char(&b, 0);
348381
return __dentry_path(dentry, &b);
349382
}
350383

@@ -397,7 +430,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size)
397430
unsigned len;
398431
DECLARE_BUFFER(b, page, PATH_MAX);
399432

400-
prepend(&b, "", 1);
433+
prepend_char(&b, 0);
401434
if (unlikely(prepend_path(&pwd, &root, &b) > 0))
402435
prepend(&b, "(unreachable)", 13);
403436
rcu_read_unlock();

0 commit comments

Comments
 (0)