| #include <vfs.h> |
| #include <kfs.h> |
| #include <slab.h> |
| #include <kmalloc.h> |
| #include <string.h> |
| #include <stdio.h> |
| #include <assert.h> |
| #include <error.h> |
| #include <cpio.h> |
| #include <pmap.h> |
| #include <smp.h> |
| |
| static char isfrog[256] = { |
| /*NUL*/ 1, 1, 1, 1, 1, 1, 1, 1, |
| /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1, |
| /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1, |
| /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1, |
| ['/'] 1, |
| [0x7f] 1, |
| }; |
| |
| /* |
| * Check that the name |
| * a) is in valid memory. |
| * b) is shorter than 2^16 bytes |
| * c) contains no frogs. |
| * The first byte is known to be addressable by the requester, so the |
| * routine works for kernel and user memory both. |
| * The parameter slashok flags whether a slash character is an error |
| * or a valid character. |
| * |
| * The parameter dup flags whether the string should be copied |
| * out of user space before being scanned the second time. |
| * (Otherwise a malicious thread could remove the NUL, causing us |
| * to access unchecked addresses.) |
| * This was from Plan 9, but the Rune support is gone. |
| * Also, we removed the 'user pointer' check, but might want it again later. |
| */ |
| char *validname0(char *aname, int slashok, int dup, uintptr_t pc) |
| { |
| char *ename, *name, *s; |
| int c, n; |
| |
| name = aname; |
| ename = memchr(name, 0, (1 << 16)); |
| |
| if (ename == NULL || ename - name >= (1 << 16)) |
| error("name too long"); |
| |
| s = NULL; |
| if (dup) { |
| n = ename - name; |
| s = kzmalloc(n + 1, KMALLOC_WAIT); |
| memmove(s, name, n); |
| s[n] = 0; |
| aname = s; |
| name = s; |
| } |
| |
| while (*name) { |
| /* all characters above '~' are ok */ |
| c = *(uint8_t *) name; |
| if (c >= Runeself) { |
| error("No UTF-8 in Akaros"); |
| } else { |
| if (isfrog[c]) |
| if (!slashok || c != '/') { |
| kfree(s); |
| error("Bad character in name"); |
| } |
| name++; |
| } |
| } |
| return s; |
| } |
| |
| /* |
| * Rather than strncpy, which zeros the rest of the buffer, kstrcpy |
| * truncates if necessary, always zero terminates, does not zero fill, |
| * and puts ... at the end of the string if it's too long. Usually used to |
| * save a string in up->genbuf; |
| */ |
| void kstrcpy(char *s, char *t, int ns) |
| { |
| int nt; |
| |
| nt = strlen(t); |
| if (nt + 1 <= ns) { |
| memmove(s, t, nt + 1); |
| return; |
| } |
| /* too long */ |
| if (ns < 4) { |
| /* but very short! */ |
| strncpy(s, t, ns); |
| return; |
| } |
| /* truncate with ... at character boundary (very rare case) */ |
| memmove(s, t, ns - 4); |
| ns -= 4; |
| s[ns] = '\0'; |
| memmove(s + ns, "...", 3); |
| } |