Merge misc fixes from Andrew Morton: "11 fixes" * emailed patches form Andrew Morton <akpm@linux-foundation.org>: reiserfs: fix buffer overflow with long warning messages checkpatch: fix duplicate invalid vsprintf pointer extension '%p<foo>' messages mm: do not bug_on on incorrect length in __mm_populate() mm/memblock.c: do not complain about top-down allocations for !MEMORY_HOTREMOVE fs, elf: make sure to page align bss in load_elf_library x86/purgatory: add missing FORCE to Makefile target net/9p/client.c: put refcount of trans_mod in error case in parse_opts() mm: allow arch to supply p??_free_tlb functions autofs: fix slab out of bounds read in getname_kernel() fs/proc/task_mmu.c: fix Locked field in /proc/pid/smaps* mm: do not drop unused pages when userfaultd is running
Unified · Split
| @@ -6,7 +6,7 @@ purgatory-y := purgatory.o stack.o setup-x86_$(BITS).o sha256.o entry64.o string · 5 unmodified lines | ||
| 6 | 6 | targets += $(purgatory-y) |
| 7 | 7 | PURGATORY_OBJS = $(addprefix $(obj)/,$(purgatory-y)) |
| 8 | 8 | |
| 9 | −$(obj)/sha256.o: $(srctree)/lib/sha256.c | |
| 9 | +$(obj)/sha256.o: $(srctree)/lib/sha256.c FORCE | |
| 10 | 10 | $(call if_changed_rule,cc_o_c) |
| 11 | 11 | |
| 12 | 12 | LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined -nostdlib -z nodefaultlib |
| @@ -135,6 +135,15 @@ static int validate_dev_ioctl(int cmd, struct autofs_dev_ioctl *param) · 134 unmodified lines | ||
| 135 | 135 | cmd); |
| 136 | 136 | goto out; |
| 137 | 137 | } |
| 138 | + } else { | |
| 139 | + unsigned int inr = _IOC_NR(cmd); | |
| 140 | + | |
| 141 | + if (inr == AUTOFS_DEV_IOCTL_OPENMOUNT_CMD || | |
| 142 | + inr == AUTOFS_DEV_IOCTL_REQUESTER_CMD || | |
| 143 | + inr == AUTOFS_DEV_IOCTL_ISMOUNTPOINT_CMD) { | |
| 144 | + err = -EINVAL; | |
| 145 | + goto out; | |
| 146 | + } | |
| 138 | 147 | } |
| 139 | 148 | |
| 140 | 149 | err = 0; |
| @@ -271,7 +280,8 @@ static int autofs_dev_ioctl_openmount(struct file *fp, · 130 unmodified lines | ||
| 271 | 280 | dev_t devid; |
| 272 | 281 | int err, fd; |
| 273 | 282 | |
| 274 | − /* param->path has already been checked */ | |
| 283 | + /* param->path has been checked in validate_dev_ioctl() */ | |
| 284 | + | |
| 275 | 285 | if (!param->openmount.devid) |
| 276 | 286 | return -EINVAL; |
| 277 | 287 | |
| @@ -433,10 +443,7 @@ static int autofs_dev_ioctl_requester(struct file *fp, · 155 unmodified lines | ||
| 433 | 443 | dev_t devid; |
| 434 | 444 | int err = -ENOENT; |
| 435 | 445 | |
| 436 | − if (param->size <= AUTOFS_DEV_IOCTL_SIZE) { | |
| 437 | − err = -EINVAL; | |
| 438 | − goto out; | |
| 439 | − } | |
| 446 | + /* param->path has been checked in validate_dev_ioctl() */ | |
| 440 | 447 | |
| 441 | 448 | devid = sbi->sb->s_dev; |
| 442 | 449 | |
| @@ -521,10 +528,7 @@ static int autofs_dev_ioctl_ismountpoint(struct file *fp, · 78 unmodified lines | ||
| 521 | 528 | unsigned int devid, magic; |
| 522 | 529 | int err = -ENOENT; |
| 523 | 530 | |
| 524 | − if (param->size <= AUTOFS_DEV_IOCTL_SIZE) { | |
| 525 | − err = -EINVAL; | |
| 526 | − goto out; | |
| 527 | − } | |
| 531 | + /* param->path has been checked in validate_dev_ioctl() */ | |
| 528 | 532 | |
| 529 | 533 | name = param->path; |
| 530 | 534 | type = param->ismountpoint.in.type; |
| @@ -1259,9 +1259,8 @@ static int load_elf_library(struct file *file) · 1258 unmodified lines | ||
| 1259 | 1259 | goto out_free_ph; |
| 1260 | 1260 | } |
| 1261 | 1261 | |
| 1262 | − len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + | |
| 1263 | − ELF_MIN_ALIGN - 1); | |
| 1264 | − bss = eppnt->p_memsz + eppnt->p_vaddr; | |
| 1262 | + len = ELF_PAGEALIGN(eppnt->p_filesz + eppnt->p_vaddr); | |
| 1263 | + bss = ELF_PAGEALIGN(eppnt->p_memsz + eppnt->p_vaddr); | |
| 1265 | 1264 | if (bss > len) { |
| 1266 | 1265 | error = vm_brk(len, bss - len); |
| 1267 | 1266 | if (error) |
| @@ -831,7 +831,8 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) · 830 unmodified lines | ||
| 831 | 831 | SEQ_PUT_DEC(" kB\nSwap: ", mss->swap); |
| 832 | 832 | SEQ_PUT_DEC(" kB\nSwapPss: ", |
| 833 | 833 | mss->swap_pss >> PSS_SHIFT); |
| 834 | − SEQ_PUT_DEC(" kB\nLocked: ", mss->pss >> PSS_SHIFT); | |
| 834 | + SEQ_PUT_DEC(" kB\nLocked: ", | |
| 835 | + mss->pss_locked >> PSS_SHIFT); | |
| 835 | 836 | seq_puts(m, " kB\n"); |
| 836 | 837 | } |
| 837 | 838 | if (!rollup_mode) { |
| @@ -76,83 +76,99 @@ static char *le_type(struct reiserfs_key *key) · 75 unmodified lines | ||
| 76 | 76 | } |
| 77 | 77 | |
| 78 | 78 | /* %k */ |
| 79 | −static void sprintf_le_key(char *buf, struct reiserfs_key *key) | |
| 79 | +static int scnprintf_le_key(char *buf, size_t size, struct reiserfs_key *key) | |
| 80 | 80 | { |
| 81 | 81 | if (key) |
| 82 | − sprintf(buf, "[%d %d %s %s]", le32_to_cpu(key->k_dir_id), | |
| 83 | − le32_to_cpu(key->k_objectid), le_offset(key), | |
| 84 | − le_type(key)); | |
| 82 | + return scnprintf(buf, size, "[%d %d %s %s]", | |
| 83 | + le32_to_cpu(key->k_dir_id), | |
| 84 | + le32_to_cpu(key->k_objectid), le_offset(key), | |
| 85 | + le_type(key)); | |
| 85 | 86 | else |
| 86 | − sprintf(buf, "[NULL]"); | |
| 87 | + return scnprintf(buf, size, "[NULL]"); | |
| 87 | 88 | } |
| 88 | 89 | |
| 89 | 90 | /* %K */ |
| 90 | −static void sprintf_cpu_key(char *buf, struct cpu_key *key) | |
| 91 | +static int scnprintf_cpu_key(char *buf, size_t size, struct cpu_key *key) | |
| 91 | 92 | { |
| 92 | 93 | if (key) |
| 93 | − sprintf(buf, "[%d %d %s %s]", key->on_disk_key.k_dir_id, | |
| 94 | − key->on_disk_key.k_objectid, reiserfs_cpu_offset(key), | |
| 95 | − cpu_type(key)); | |
| 94 | + return scnprintf(buf, size, "[%d %d %s %s]", | |
| 95 | + key->on_disk_key.k_dir_id, | |
| 96 | + key->on_disk_key.k_objectid, | |
| 97 | + reiserfs_cpu_offset(key), cpu_type(key)); | |
| 96 | 98 | else |
| 97 | − sprintf(buf, "[NULL]"); | |
| 99 | + return scnprintf(buf, size, "[NULL]"); | |
| 98 | 100 | } |
| 99 | 101 | |
| 100 | −static void sprintf_de_head(char *buf, struct reiserfs_de_head *deh) | |
| 102 | +static int scnprintf_de_head(char *buf, size_t size, | |
| 103 | + struct reiserfs_de_head *deh) | |
| 101 | 104 | { |
| 102 | 105 | if (deh) |
| 103 | − sprintf(buf, | |
| 104 | − "[offset=%d dir_id=%d objectid=%d location=%d state=%04x]", | |
| 105 | − deh_offset(deh), deh_dir_id(deh), deh_objectid(deh), | |
| 106 | − deh_location(deh), deh_state(deh)); | |
| 106 | + return scnprintf(buf, size, | |
| 107 | + "[offset=%d dir_id=%d objectid=%d location=%d state=%04x]", | |
| 108 | + deh_offset(deh), deh_dir_id(deh), | |
| 109 | + deh_objectid(deh), deh_location(deh), | |
| 110 | + deh_state(deh)); | |
| 107 | 111 | else |
| 108 | − sprintf(buf, "[NULL]"); | |
| 112 | + return scnprintf(buf, size, "[NULL]"); | |
| 109 | 113 | |
| 110 | 114 | } |
| 111 | 115 | |
| 112 | −static void sprintf_item_head(char *buf, struct item_head *ih) | |
| 116 | +static int scnprintf_item_head(char *buf, size_t size, struct item_head *ih) | |
| 113 | 117 | { |
| 114 | 118 | if (ih) { |
| 115 | − strcpy(buf, | |
| 116 | − (ih_version(ih) == KEY_FORMAT_3_6) ? "*3.6* " : "*3.5*"); | |
| 117 | − sprintf_le_key(buf + strlen(buf), &(ih->ih_key)); | |
| 118 | − sprintf(buf + strlen(buf), ", item_len %d, item_location %d, " | |
| 119 | − "free_space(entry_count) %d", | |
| 120 | − ih_item_len(ih), ih_location(ih), ih_free_space(ih)); | |
| 119 | + char *p = buf; | |
| 120 | + char * const end = buf + size; | |
| 121 | + | |
| 122 | + p += scnprintf(p, end - p, "%s", | |
| 123 | + (ih_version(ih) == KEY_FORMAT_3_6) ? | |
| 124 | + "*3.6* " : "*3.5*"); | |
| 125 | + | |
| 126 | + p += scnprintf_le_key(p, end - p, &ih->ih_key); | |
| 127 | + | |
| 128 | + p += scnprintf(p, end - p, | |
| 129 | + ", item_len %d, item_location %d, free_space(entry_count) %d", | |
| 130 | + ih_item_len(ih), ih_location(ih), | |
| 131 | + ih_free_space(ih)); | |
| 132 | + return p - buf; | |
| 121 | 133 | } else |
| 122 | − sprintf(buf, "[NULL]"); | |
| 134 | + return scnprintf(buf, size, "[NULL]"); | |
| 123 | 135 | } |
| 124 | 136 | |
| 125 | −static void sprintf_direntry(char *buf, struct reiserfs_dir_entry *de) | |
| 137 | +static int scnprintf_direntry(char *buf, size_t size, | |
| 138 | + struct reiserfs_dir_entry *de) | |
| 126 | 139 | { |
| 127 | 140 | char name[20]; |
| 128 | 141 | |
| 129 | 142 | memcpy(name, de->de_name, de->de_namelen > 19 ? 19 : de->de_namelen); |
| 130 | 143 | name[de->de_namelen > 19 ? 19 : de->de_namelen] = 0; |
| 131 | − sprintf(buf, "\"%s\"==>[%d %d]", name, de->de_dir_id, de->de_objectid); | |
| 144 | + return scnprintf(buf, size, "\"%s\"==>[%d %d]", | |
| 145 | + name, de->de_dir_id, de->de_objectid); | |
| 132 | 146 | } |
| 133 | 147 | |
| 134 | −static void sprintf_block_head(char *buf, struct buffer_head *bh) | |
| 148 | +static int scnprintf_block_head(char *buf, size_t size, struct buffer_head *bh) | |
| 135 | 149 | { |
| 136 | − sprintf(buf, "level=%d, nr_items=%d, free_space=%d rdkey ", | |
| 137 | − B_LEVEL(bh), B_NR_ITEMS(bh), B_FREE_SPACE(bh)); | |
| 150 | + return scnprintf(buf, size, | |
| 151 | + "level=%d, nr_items=%d, free_space=%d rdkey ", | |
| 152 | + B_LEVEL(bh), B_NR_ITEMS(bh), B_FREE_SPACE(bh)); | |
| 138 | 153 | } |
| 139 | 154 | |
| 140 | −static void sprintf_buffer_head(char *buf, struct buffer_head *bh) | |
| 155 | +static int scnprintf_buffer_head(char *buf, size_t size, struct buffer_head *bh) | |
| 141 | 156 | { |
| 142 | − sprintf(buf, | |
| 143 | − "dev %pg, size %zd, blocknr %llu, count %d, state 0x%lx, page %p, (%s, %s, %s)", | |
| 144 | − bh->b_bdev, bh->b_size, | |
| 145 | − (unsigned long long)bh->b_blocknr, atomic_read(&(bh->b_count)), | |
| 146 | − bh->b_state, bh->b_page, | |
| 147 | − buffer_uptodate(bh) ? "UPTODATE" : "!UPTODATE", | |
| 148 | − buffer_dirty(bh) ? "DIRTY" : "CLEAN", | |
| 149 | − buffer_locked(bh) ? "LOCKED" : "UNLOCKED"); | |
| 157 | + return scnprintf(buf, size, | |
| 158 | + "dev %pg, size %zd, blocknr %llu, count %d, state 0x%lx, page %p, (%s, %s, %s)", | |
| 159 | + bh->b_bdev, bh->b_size, | |
| 160 | + (unsigned long long)bh->b_blocknr, | |
| 161 | + atomic_read(&(bh->b_count)), | |
| 162 | + bh->b_state, bh->b_page, | |
| 163 | + buffer_uptodate(bh) ? "UPTODATE" : "!UPTODATE", | |
| 164 | + buffer_dirty(bh) ? "DIRTY" : "CLEAN", | |
| 165 | + buffer_locked(bh) ? "LOCKED" : "UNLOCKED"); | |
| 150 | 166 | } |
| 151 | 167 | |
| 152 | −static void sprintf_disk_child(char *buf, struct disk_child *dc) | |
| 168 | +static int scnprintf_disk_child(char *buf, size_t size, struct disk_child *dc) | |
| 153 | 169 | { |
| 154 | − sprintf(buf, "[dc_number=%d, dc_size=%u]", dc_block_number(dc), | |
| 155 | − dc_size(dc)); | |
| 170 | + return scnprintf(buf, size, "[dc_number=%d, dc_size=%u]", | |
| 171 | + dc_block_number(dc), dc_size(dc)); | |
| 156 | 172 | } |
| 157 | 173 | |
| 158 | 174 | static char *is_there_reiserfs_struct(char *fmt, int *what) |
| @@ -189,55 +205,60 @@ static void prepare_error_buf(const char *fmt, va_list args) · 30 unmodified lines | ||
| 189 | 205 | char *fmt1 = fmt_buf; |
| 190 | 206 | char *k; |
| 191 | 207 | char *p = error_buf; |
| 208 | + char * const end = &error_buf[sizeof(error_buf)]; | |
| 192 | 209 | int what; |
| 193 | 210 | |
| 194 | 211 | spin_lock(&error_lock); |
| 195 | 212 | |
| 196 | − strcpy(fmt1, fmt); | |
| 213 | + if (WARN_ON(strscpy(fmt_buf, fmt, sizeof(fmt_buf)) < 0)) { | |
| 214 | + strscpy(error_buf, "format string too long", end - error_buf); | |
| 215 | + goto out_unlock; | |
| 216 | + } | |
| 197 | 217 | |
| 198 | 218 | while ((k = is_there_reiserfs_struct(fmt1, &what)) != NULL) { |
| 199 | 219 | *k = 0; |
| 200 | 220 | |
| 201 | − p += vsprintf(p, fmt1, args); | |
| 221 | + p += vscnprintf(p, end - p, fmt1, args); | |
| 202 | 222 | |
| 203 | 223 | switch (what) { |
| 204 | 224 | case 'k': |
| 205 | − sprintf_le_key(p, va_arg(args, struct reiserfs_key *)); | |
| 225 | + p += scnprintf_le_key(p, end - p, | |
| 226 | + va_arg(args, struct reiserfs_key *)); | |
| 206 | 227 | break; |
| 207 | 228 | case 'K': |
| 208 | − sprintf_cpu_key(p, va_arg(args, struct cpu_key *)); | |
| 229 | + p += scnprintf_cpu_key(p, end - p, | |
| 230 | + va_arg(args, struct cpu_key *)); | |
| 209 | 231 | break; |
| 210 | 232 | case 'h': |
| 211 | − sprintf_item_head(p, va_arg(args, struct item_head *)); | |
| 233 | + p += scnprintf_item_head(p, end - p, | |
| 234 | + va_arg(args, struct item_head *)); | |
| 212 | 235 | break; |
| 213 | 236 | case 't': |
| 214 | − sprintf_direntry(p, | |
| 215 | − va_arg(args, | |
| 216 | − struct reiserfs_dir_entry *)); | |
| 237 | + p += scnprintf_direntry(p, end - p, | |
| 238 | + va_arg(args, struct reiserfs_dir_entry *)); | |
| 217 | 239 | break; |
| 218 | 240 | case 'y': |
| 219 | − sprintf_disk_child(p, | |
| 220 | − va_arg(args, struct disk_child *)); | |
| 241 | + p += scnprintf_disk_child(p, end - p, | |
| 242 | + va_arg(args, struct disk_child *)); | |
| 221 | 243 | break; |
| 222 | 244 | case 'z': |
| 223 | − sprintf_block_head(p, | |
| 224 | − va_arg(args, struct buffer_head *)); | |
| 245 | + p += scnprintf_block_head(p, end - p, | |
| 246 | + va_arg(args, struct buffer_head *)); | |
| 225 | 247 | break; |
| 226 | 248 | case 'b': |
| 227 | − sprintf_buffer_head(p, | |
| 228 | − va_arg(args, struct buffer_head *)); | |
| 249 | + p += scnprintf_buffer_head(p, end - p, | |
| 250 | + va_arg(args, struct buffer_head *)); | |
| 229 | 251 | break; |
| 230 | 252 | case 'a': |
| 231 | − sprintf_de_head(p, | |
| 232 | − va_arg(args, | |
| 233 | − struct reiserfs_de_head *)); | |
| 253 | + p += scnprintf_de_head(p, end - p, | |
| 254 | + va_arg(args, struct reiserfs_de_head *)); | |
| 234 | 255 | break; |
| 235 | 256 | } |
| 236 | 257 | |
| 237 | − p += strlen(p); | |
| 238 | 258 | fmt1 = k + 2; |
| 239 | 259 | } |
| 240 | − vsprintf(p, fmt1, args); | |
| 260 | + p += vscnprintf(p, end - p, fmt1, args); | |
| 261 | +out_unlock: | |
| 241 | 262 | spin_unlock(&error_lock); |
| 242 | 263 | |
| 243 | 264 | } |
| @@ -265,33 +265,41 @@ static inline void tlb_remove_check_page_size_change(struct mmu_gather *tlb, · 264 unmodified lines | ||
| 265 | 265 | * For now w.r.t page table cache, mark the range_size as PAGE_SIZE |
| 266 | 266 | */ |
| 267 | 267 | |
| 268 | +#ifndef pte_free_tlb | |
| 268 | 269 | #define pte_free_tlb(tlb, ptep, address) \ |
| 269 | 270 | do { \ |
| 270 | 271 | __tlb_adjust_range(tlb, address, PAGE_SIZE); \ |
| 271 | 272 | __pte_free_tlb(tlb, ptep, address); \ |
| 272 | 273 | } while (0) |
| 274 | +#endif | |
| 273 | 275 | |
| 276 | +#ifndef pmd_free_tlb | |
| 274 | 277 | #define pmd_free_tlb(tlb, pmdp, address) \ |
| 275 | 278 | do { \ |
| 276 | 279 | __tlb_adjust_range(tlb, address, PAGE_SIZE); \ |
| 277 | 280 | __pmd_free_tlb(tlb, pmdp, address); \ |
| 278 | 281 | } while (0) |
| 282 | +#endif | |
| 279 | 283 | |
| 280 | 284 | #ifndef __ARCH_HAS_4LEVEL_HACK |
| 285 | +#ifndef pud_free_tlb | |
| 281 | 286 | #define pud_free_tlb(tlb, pudp, address) \ |
| 282 | 287 | do { \ |
| 283 | 288 | __tlb_adjust_range(tlb, address, PAGE_SIZE); \ |
| 284 | 289 | __pud_free_tlb(tlb, pudp, address); \ |
| 285 | 290 | } while (0) |
| 286 | 291 | #endif |
| 292 | +#endif | |
| 287 | 293 | |
| 288 | 294 | #ifndef __ARCH_HAS_5LEVEL_HACK |
| 295 | +#ifndef p4d_free_tlb | |
| 289 | 296 | #define p4d_free_tlb(tlb, pudp, address) \ |
| 290 | 297 | do { \ |
| 291 | 298 | __tlb_adjust_range(tlb, address, PAGE_SIZE); \ |
| 292 | 299 | __p4d_free_tlb(tlb, pudp, address); \ |
| 293 | 300 | } while (0) |
| 294 | 301 | #endif |
| 302 | +#endif | |
| 295 | 303 | |
| 296 | 304 | #define tlb_migrate_finish(mm) do {} while (0) |
| 297 | 305 | |
| @@ -1238,8 +1238,6 @@ int __mm_populate(unsigned long start, unsigned long len, int ignore_errors) · 1237 unmodified lines | ||
| 1238 | 1238 | int locked = 0; |
| 1239 | 1239 | long ret = 0; |
| 1240 | 1240 | |
| 1241 | − VM_BUG_ON(start & ~PAGE_MASK); | |
| 1242 | − VM_BUG_ON(len != PAGE_ALIGN(len)); | |
| 1243 | 1241 | end = start + len; |
| 1244 | 1242 | |
| 1245 | 1243 | for (nstart = start; nstart < end; nstart = nend) { |
| @@ -227,7 +227,8 @@ phys_addr_t __init_memblock memblock_find_in_range_node(phys_addr_t size, · 226 unmodified lines | ||
| 227 | 227 | * so we use WARN_ONCE() here to see the stack trace if |
| 228 | 228 | * fail happens. |
| 229 | 229 | */ |
| 230 | − WARN_ONCE(1, "memblock: bottom-up allocation failed, memory hotunplug may be affected\n"); | |
| 230 | + WARN_ONCE(IS_ENABLED(CONFIG_MEMORY_HOTREMOVE), | |
| 231 | + "memblock: bottom-up allocation failed, memory hotremove may be affected\n"); | |
| 231 | 232 | } |
| 232 | 233 | |
| 233 | 234 | return __memblock_find_range_top_down(start, end, size, align, nid, |
| @@ -186,8 +186,8 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) · 185 unmodified lines | ||
| 186 | 186 | return next; |
| 187 | 187 | } |
| 188 | 188 | |
| 189 | −static int do_brk(unsigned long addr, unsigned long len, struct list_head *uf); | |
| 190 | − | |
| 189 | +static int do_brk_flags(unsigned long addr, unsigned long request, unsigned long flags, | |
| 190 | + struct list_head *uf); | |
| 191 | 191 | SYSCALL_DEFINE1(brk, unsigned long, brk) |
| 192 | 192 | { |
| 193 | 193 | unsigned long retval; |
| @@ -245,7 +245,7 @@ SYSCALL_DEFINE1(brk, unsigned long, brk) · 51 unmodified lines | ||
| 245 | 245 | goto out; |
| 246 | 246 | |
| 247 | 247 | /* Ok, looks good - let it rip. */ |
| 248 | − if (do_brk(oldbrk, newbrk-oldbrk, &uf) < 0) | |
| 248 | + if (do_brk_flags(oldbrk, newbrk-oldbrk, 0, &uf) < 0) | |
| 249 | 249 | goto out; |
| 250 | 250 | |
| 251 | 251 | set_brk: |
| @@ -2929,21 +2929,14 @@ static inline void verify_mm_writelocked(struct mm_struct *mm) · 2677 unmodified lines | ||
| 2929 | 2929 | * anonymous maps. eventually we may be able to do some |
| 2930 | 2930 | * brk-specific accounting here. |
| 2931 | 2931 | */ |
| 2932 | −static int do_brk_flags(unsigned long addr, unsigned long request, unsigned long flags, struct list_head *uf) | |
| 2932 | +static int do_brk_flags(unsigned long addr, unsigned long len, unsigned long flags, struct list_head *uf) | |
| 2933 | 2933 | { |
| 2934 | 2934 | struct mm_struct *mm = current->mm; |
| 2935 | 2935 | struct vm_area_struct *vma, *prev; |
| 2936 | − unsigned long len; | |
| 2937 | 2936 | struct rb_node **rb_link, *rb_parent; |
| 2938 | 2937 | pgoff_t pgoff = addr >> PAGE_SHIFT; |
| 2939 | 2938 | int error; |
| 2940 | 2939 | |
| 2941 | − len = PAGE_ALIGN(request); | |
| 2942 | − if (len < request) | |
| 2943 | − return -ENOMEM; | |
| 2944 | − if (!len) | |
| 2945 | − return 0; | |
| 2946 | − | |
| 2947 | 2940 | /* Until we need other flags, refuse anything except VM_EXEC. */ |
| 2948 | 2941 | if ((flags & (~VM_EXEC)) != 0) |
| 2949 | 2942 | return -EINVAL; |
| @@ -3015,18 +3008,20 @@ out: · 65 unmodified lines | ||
| 3015 | 3008 | return 0; |
| 3016 | 3009 | } |
| 3017 | 3010 | |
| 3018 | −static int do_brk(unsigned long addr, unsigned long len, struct list_head *uf) | |
| 3019 | −{ | |
| 3020 | − return do_brk_flags(addr, len, 0, uf); | |
| 3021 | −} | |
| 3022 | − | |
| 3023 | −int vm_brk_flags(unsigned long addr, unsigned long len, unsigned long flags) | |
| 3011 | +int vm_brk_flags(unsigned long addr, unsigned long request, unsigned long flags) | |
| 3024 | 3012 | { |
| 3025 | 3013 | struct mm_struct *mm = current->mm; |
| 3014 | + unsigned long len; | |
| 3026 | 3015 | int ret; |
| 3027 | 3016 | bool populate; |
| 3028 | 3017 | LIST_HEAD(uf); |
| 3029 | 3018 | |
| 3019 | + len = PAGE_ALIGN(request); | |
| 3020 | + if (len < request) | |
| 3021 | + return -ENOMEM; | |
| 3022 | + if (!len) | |
| 3023 | + return 0; | |
| 3024 | + | |
| 3030 | 3025 | if (down_write_killable(&mm->mmap_sem)) |
| 3031 | 3026 | return -EINTR; |
| 3032 | 3027 | |
| @@ -64,6 +64,7 @@ · 63 unmodified lines | ||
| 64 | 64 | #include <linux/backing-dev.h> |
| 65 | 65 | #include <linux/page_idle.h> |
| 66 | 66 | #include <linux/memremap.h> |
| 67 | +#include <linux/userfaultfd_k.h> | |
| 67 | 68 | |
| 68 | 69 | #include <asm/tlbflush.h> |
| 69 | 70 | |
| @@ -1481,11 +1482,16 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, · 1411 unmodified lines | ||
| 1481 | 1482 | set_pte_at(mm, address, pvmw.pte, pteval); |
| 1482 | 1483 | } |
| 1483 | 1484 | |
| 1484 | − } else if (pte_unused(pteval)) { | |
| 1485 | + } else if (pte_unused(pteval) && !userfaultfd_armed(vma)) { | |
| 1485 | 1486 | /* |
| 1486 | 1487 | * The guest indicated that the page content is of no |
| 1487 | 1488 | * interest anymore. Simply discard the pte, vmscan |
| 1488 | 1489 | * will take care of the rest. |
| 1490 | + * A future reference will then fault in a new zero | |
| 1491 | + * page. When userfaultfd is active, we must not drop | |
| 1492 | + * this page though, as its main user (postcopy | |
| 1493 | + * migration) will not expect userfaults on already | |
| 1494 | + * copied pages. | |
| 1489 | 1495 | */ |
| 1490 | 1496 | dec_mm_counter(mm, mm_counter(page)); |
| 1491 | 1497 | /* We have to invalidate as we cleared the pte */ |
| @@ -225,7 +225,8 @@ static int parse_opts(char *opts, struct p9_client *clnt) · 224 unmodified lines | ||
| 225 | 225 | } |
| 226 | 226 | |
| 227 | 227 | free_and_return: |
| 228 | − v9fs_put_trans(clnt->trans_mod); | |
| 228 | + if (ret) | |
| 229 | + v9fs_put_trans(clnt->trans_mod); | |
| 229 | 230 | kfree(tmp_options); |
| 230 | 231 | return ret; |
| 231 | 232 | } |
| @@ -5813,14 +5813,14 @@ sub process { · 5812 unmodified lines | ||
| 5813 | 5813 | defined $stat && |
| 5814 | 5814 | $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s && |
| 5815 | 5815 | $1 !~ /^_*volatile_*$/) { |
| 5816 | − my $specifier; | |
| 5817 | − my $extension; | |
| 5818 | − my $bad_specifier = ""; | |
| 5819 | 5816 | my $stat_real; |
| 5820 | 5817 | |
| 5821 | 5818 | my $lc = $stat =~ tr@\n@@; |
| 5822 | 5819 | $lc = $lc + $linenr; |
| 5823 | 5820 | for (my $count = $linenr; $count <= $lc; $count++) { |
| 5821 | + my $specifier; | |
| 5822 | + my $extension; | |
| 5823 | + my $bad_specifier = ""; | |
| 5824 | 5824 | my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0)); |
| 5825 | 5825 | $fmt =~ s/%%//g; |
| 5826 | 5826 | |