Pull misc updates from Andrew Morton: "Updates to various subsystems which I help look after. lib, ocfs2, fatfs, autofs, squashfs, procfs, etc. A relatively small amount of material this time" * tag 'mm-nonmm-stable-2022-08-06-2' of git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm: (72 commits) scripts/gdb: ensure the absolute path is generated on initial source MAINTAINERS: kunit: add David Gow as a maintainer of KUnit mailmap: add linux.dev alias for Brendan Higgins mailmap: update Kirill's email profile: setup_profiling_timer() is moslty not implemented ocfs2: fix a typo in a comment ocfs2: use the bitmap API to simplify code ocfs2: remove some useless functions lib/mpi: fix typo 'the the' in comment proc: add some (hopefully) insightful comments bdi: remove enum wb_congested_state kernel/hung_task: fix address space of proc_dohung_task_timeout_secs lib/lzo/lzo1x_compress.c: replace ternary operator with min() and min_t() squashfs: support reading fragments in readahead call squashfs: implement readahead squashfs: always build "file direct" version of page actor Revert "squashfs: provide backing_dev_info in order to disable read-ahead" fs/ocfs2: Fix spelling typo in comment ia64: old_rr4 added under CONFIG_HUGETLB_PAGE proc: fix test for "vsyscall=xonly" boot option ...
Showing the changes to tools/testing (7 of 102 files). Show all
Unified · Split
| @@ -17,6 +17,7 @@ TARGETS += exec · 16 unmodified lines | ||
| 17 | 17 | TARGETS += filesystems |
| 18 | 18 | TARGETS += filesystems/binderfs |
| 19 | 19 | TARGETS += filesystems/epoll |
| 20 | +TARGETS += filesystems/fat | |
| 20 | 21 | TARGETS += firmware |
| 21 | 22 | TARGETS += fpu |
| 22 | 23 | TARGETS += ftrace |
| @@ -0,0 +1,2 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0-only | |
| 2 | +rename_exchange | |
| @@ -0,0 +1,7 @@ | ||
| 1 | +# SPDX-License-Identifier: GPL-2.0 | |
| 2 | + | |
| 3 | +TEST_PROGS := run_fat_tests.sh | |
| 4 | +TEST_GEN_PROGS_EXTENDED := rename_exchange | |
| 5 | +CFLAGS += -O2 -g -Wall $(KHDR_INCLUDES) | |
| 6 | + | |
| 7 | +include ../../lib.mk | |
| @@ -0,0 +1,2 @@ | ||
| 1 | +CONFIG_BLK_DEV_LOOP=y | |
| 2 | +CONFIG_VFAT_FS=y | |
| @@ -0,0 +1,37 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later | |
| 2 | +/* | |
| 3 | + * Program that atomically exchanges two paths using | |
| 4 | + * the renameat2() system call RENAME_EXCHANGE flag. | |
| 5 | + * | |
| 6 | + * Copyright 2022 Red Hat Inc. | |
| 7 | + * Author: Javier Martinez Canillas <javierm@redhat.com> | |
| 8 | + */ | |
| 9 | + | |
| 10 | +#define _GNU_SOURCE | |
| 11 | +#include <fcntl.h> | |
| 12 | +#include <stdio.h> | |
| 13 | +#include <stdlib.h> | |
| 14 | + | |
| 15 | +void print_usage(const char *program) | |
| 16 | +{ | |
| 17 | + printf("Usage: %s [oldpath] [newpath]\n", program); | |
| 18 | + printf("Atomically exchange oldpath and newpath\n"); | |
| 19 | +} | |
| 20 | + | |
| 21 | +int main(int argc, char *argv[]) | |
| 22 | +{ | |
| 23 | + int ret; | |
| 24 | + | |
| 25 | + if (argc != 3) { | |
| 26 | + print_usage(argv[0]); | |
| 27 | + exit(EXIT_FAILURE); | |
| 28 | + } | |
| 29 | + | |
| 30 | + ret = renameat2(AT_FDCWD, argv[1], AT_FDCWD, argv[2], RENAME_EXCHANGE); | |
| 31 | + if (ret) { | |
| 32 | + perror("rename exchange failed"); | |
| 33 | + exit(EXIT_FAILURE); | |
| 34 | + } | |
| 35 | + | |
| 36 | + exit(EXIT_SUCCESS); | |
| 37 | +} | |
| @@ -0,0 +1,82 @@ | ||
| 1 | +#!/bin/bash | |
| 2 | +# SPDX-License-Identifier: GPL-2.0 | |
| 3 | +# | |
| 4 | +# Run filesystem operations tests on an 1 MiB disk image that is formatted with | |
| 5 | +# a vfat filesystem and mounted in a temporary directory using a loop device. | |
| 6 | +# | |
| 7 | +# Copyright 2022 Red Hat Inc. | |
| 8 | +# Author: Javier Martinez Canillas <javierm@redhat.com> | |
| 9 | + | |
| 10 | +set -e | |
| 11 | +set -u | |
| 12 | +set -o pipefail | |
| 13 | + | |
| 14 | +BASE_DIR="$(dirname $0)" | |
| 15 | +TMP_DIR="$(mktemp -d /tmp/fat_tests_tmp.XXXX)" | |
| 16 | +IMG_PATH="${TMP_DIR}/fat.img" | |
| 17 | +MNT_PATH="${TMP_DIR}/mnt" | |
| 18 | + | |
| 19 | +cleanup() | |
| 20 | +{ | |
| 21 | + mountpoint -q "${MNT_PATH}" && unmount_image | |
| 22 | + rm -rf "${TMP_DIR}" | |
| 23 | +} | |
| 24 | +trap cleanup SIGINT SIGTERM EXIT | |
| 25 | + | |
| 26 | +create_loopback() | |
| 27 | +{ | |
| 28 | + touch "${IMG_PATH}" | |
| 29 | + chattr +C "${IMG_PATH}" >/dev/null 2>&1 || true | |
| 30 | + | |
| 31 | + truncate -s 1M "${IMG_PATH}" | |
| 32 | + mkfs.vfat "${IMG_PATH}" >/dev/null 2>&1 | |
| 33 | +} | |
| 34 | + | |
| 35 | +mount_image() | |
| 36 | +{ | |
| 37 | + mkdir -p "${MNT_PATH}" | |
| 38 | + sudo mount -o loop "${IMG_PATH}" "${MNT_PATH}" | |
| 39 | +} | |
| 40 | + | |
| 41 | +rename_exchange_test() | |
| 42 | +{ | |
| 43 | + local rename_exchange="${BASE_DIR}/rename_exchange" | |
| 44 | + local old_path="${MNT_PATH}/old_file" | |
| 45 | + local new_path="${MNT_PATH}/new_file" | |
| 46 | + | |
| 47 | + echo old | sudo tee "${old_path}" >/dev/null 2>&1 | |
| 48 | + echo new | sudo tee "${new_path}" >/dev/null 2>&1 | |
| 49 | + sudo "${rename_exchange}" "${old_path}" "${new_path}" >/dev/null 2>&1 | |
| 50 | + sudo sync -f "${MNT_PATH}" | |
| 51 | + grep new "${old_path}" >/dev/null 2>&1 | |
| 52 | + grep old "${new_path}" >/dev/null 2>&1 | |
| 53 | +} | |
| 54 | + | |
| 55 | +rename_exchange_subdir_test() | |
| 56 | +{ | |
| 57 | + local rename_exchange="${BASE_DIR}/rename_exchange" | |
| 58 | + local dir_path="${MNT_PATH}/subdir" | |
| 59 | + local old_path="${MNT_PATH}/old_file" | |
| 60 | + local new_path="${dir_path}/new_file" | |
| 61 | + | |
| 62 | + sudo mkdir -p "${dir_path}" | |
| 63 | + echo old | sudo tee "${old_path}" >/dev/null 2>&1 | |
| 64 | + echo new | sudo tee "${new_path}" >/dev/null 2>&1 | |
| 65 | + sudo "${rename_exchange}" "${old_path}" "${new_path}" >/dev/null 2>&1 | |
| 66 | + sudo sync -f "${MNT_PATH}" | |
| 67 | + grep new "${old_path}" >/dev/null 2>&1 | |
| 68 | + grep old "${new_path}" >/dev/null 2>&1 | |
| 69 | +} | |
| 70 | + | |
| 71 | +unmount_image() | |
| 72 | +{ | |
| 73 | + sudo umount "${MNT_PATH}" &> /dev/null | |
| 74 | +} | |
| 75 | + | |
| 76 | +create_loopback | |
| 77 | +mount_image | |
| 78 | +rename_exchange_test | |
| 79 | +rename_exchange_subdir_test | |
| 80 | +unmount_image | |
| 81 | + | |
| 82 | +exit 0 | |
| @@ -211,10 +211,19 @@ static int make_exe(const uint8_t *payload, size_t len) · 210 unmodified lines | ||
| 211 | 211 | } |
| 212 | 212 | #endif |
| 213 | 213 | |
| 214 | −static bool g_vsyscall = false; | |
| 214 | +/* | |
| 215 | + * 0: vsyscall VMA doesn't exist vsyscall=none | |
| 216 | + * 1: vsyscall VMA is r-xp vsyscall=emulate | |
| 217 | + * 2: vsyscall VMA is --xp vsyscall=xonly | |
| 218 | + */ | |
| 219 | +static int g_vsyscall; | |
| 220 | +static const char *str_vsyscall; | |
| 215 | 221 | |
| 216 | −static const char str_vsyscall[] = | |
| 222 | +static const char str_vsyscall_0[] = ""; | |
| 223 | +static const char str_vsyscall_1[] = | |
| 217 | 224 | "ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n"; |
| 225 | +static const char str_vsyscall_2[] = | |
| 226 | +"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]\n"; | |
| 218 | 227 | |
| 219 | 228 | #ifdef __x86_64__ |
| 220 | 229 | static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___) |
| @@ -223,13 +232,47 @@ static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___) · 2 unmodified lines | ||
| 223 | 232 | } |
| 224 | 233 | |
| 225 | 234 | /* |
| 226 | − * vsyscall page can't be unmapped, probe it with memory load. | |
| 235 | + * vsyscall page can't be unmapped, probe it directly. | |
| 227 | 236 | */ |
| 228 | 237 | static void vsyscall(void) |
| 229 | 238 | { |
| 230 | 239 | pid_t pid; |
| 231 | 240 | int wstatus; |
| 232 | 241 | |
| 242 | + pid = fork(); | |
| 243 | + if (pid < 0) { | |
| 244 | + fprintf(stderr, "fork, errno %d\n", errno); | |
| 245 | + exit(1); | |
| 246 | + } | |
| 247 | + if (pid == 0) { | |
| 248 | + struct rlimit rlim = {0, 0}; | |
| 249 | + (void)setrlimit(RLIMIT_CORE, &rlim); | |
| 250 | + | |
| 251 | + /* Hide "segfault at ffffffffff600000" messages. */ | |
| 252 | + struct sigaction act; | |
| 253 | + memset(&act, 0, sizeof(struct sigaction)); | |
| 254 | + act.sa_flags = SA_SIGINFO; | |
| 255 | + act.sa_sigaction = sigaction_SIGSEGV; | |
| 256 | + (void)sigaction(SIGSEGV, &act, NULL); | |
| 257 | + | |
| 258 | + /* gettimeofday(NULL, NULL); */ | |
| 259 | + asm volatile ( | |
| 260 | + "call %P0" | |
| 261 | + : | |
| 262 | + : "i" (0xffffffffff600000), "D" (NULL), "S" (NULL) | |
| 263 | + : "rax", "rcx", "r11" | |
| 264 | + ); | |
| 265 | + exit(0); | |
| 266 | + } | |
| 267 | + waitpid(pid, &wstatus, 0); | |
| 268 | + if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) { | |
| 269 | + /* vsyscall page exists and is executable. */ | |
| 270 | + } else { | |
| 271 | + /* vsyscall page doesn't exist. */ | |
| 272 | + g_vsyscall = 0; | |
| 273 | + return; | |
| 274 | + } | |
| 275 | + | |
| 233 | 276 | pid = fork(); |
| 234 | 277 | if (pid < 0) { |
| 235 | 278 | fprintf(stderr, "fork, errno %d\n", errno); |
| @@ -251,8 +294,13 @@ static void vsyscall(void) · 15 unmodified lines | ||
| 251 | 294 | } |
| 252 | 295 | waitpid(pid, &wstatus, 0); |
| 253 | 296 | if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) { |
| 254 | − g_vsyscall = true; | |
| 297 | + /* vsyscall page is readable and executable. */ | |
| 298 | + g_vsyscall = 1; | |
| 299 | + return; | |
| 255 | 300 | } |
| 301 | + | |
| 302 | + /* vsyscall page is executable but unreadable. */ | |
| 303 | + g_vsyscall = 2; | |
| 256 | 304 | } |
| 257 | 305 | |
| 258 | 306 | int main(void) |
| @@ -261,6 +309,19 @@ int main(void) · 2 unmodified lines | ||
| 261 | 309 | int exec_fd; |
| 262 | 310 | |
| 263 | 311 | vsyscall(); |
| 312 | + switch (g_vsyscall) { | |
| 313 | + case 0: | |
| 314 | + str_vsyscall = str_vsyscall_0; | |
| 315 | + break; | |
| 316 | + case 1: | |
| 317 | + str_vsyscall = str_vsyscall_1; | |
| 318 | + break; | |
| 319 | + case 2: | |
| 320 | + str_vsyscall = str_vsyscall_2; | |
| 321 | + break; | |
| 322 | + default: | |
| 323 | + abort(); | |
| 324 | + } | |
| 264 | 325 | |
| 265 | 326 | atexit(ate); |
| 266 | 327 | |
| @@ -314,7 +375,7 @@ int main(void) · 47 unmodified lines | ||
| 314 | 375 | |
| 315 | 376 | /* Test /proc/$PID/maps */ |
| 316 | 377 | { |
| 317 | − const size_t len = strlen(buf0) + (g_vsyscall ? strlen(str_vsyscall) : 0); | |
| 378 | + const size_t len = strlen(buf0) + strlen(str_vsyscall); | |
| 318 | 379 | char buf[256]; |
| 319 | 380 | ssize_t rv; |
| 320 | 381 | int fd; |
| @@ -327,7 +388,7 @@ int main(void) · 6 unmodified lines | ||
| 327 | 388 | rv = read(fd, buf, sizeof(buf)); |
| 328 | 389 | assert(rv == len); |
| 329 | 390 | assert(memcmp(buf, buf0, strlen(buf0)) == 0); |
| 330 | − if (g_vsyscall) { | |
| 391 | + if (g_vsyscall > 0) { | |
| 331 | 392 | assert(memcmp(buf + strlen(buf0), str_vsyscall, strlen(str_vsyscall)) == 0); |
| 332 | 393 | } |
| 333 | 394 | } |
| @@ -374,7 +435,7 @@ int main(void) · 40 unmodified lines | ||
| 374 | 435 | assert(memmem(buf, rv, S[i], strlen(S[i]))); |
| 375 | 436 | } |
| 376 | 437 | |
| 377 | − if (g_vsyscall) { | |
| 438 | + if (g_vsyscall > 0) { | |
| 378 | 439 | assert(memmem(buf, rv, str_vsyscall, strlen(str_vsyscall))); |
| 379 | 440 | } |
| 380 | 441 | } |