tests: extend coverage of execve and execveat syscalls
Check decoding of inaccessible or partially inaccessible arrays. * tests/execve-v.c: New file. * tests/execveat-v.c: Likewise. * tests/execve-v.test: New test. * tests/execveat-v.test: Likewise. * tests/execve.c: Rewrite. * tests/execveat.c: Likewise. * tests/execve.test: Likewise. * tests/execveat.test: Likewise. * tests/execve.expected: Remove. * tests/execve-v.expected: Likewise. * tests/execveat.expected: Likewise. * tests/execveat-v.expected: Likewise. * tests/.gitignore: Add execve-v and execveat-v. * tests/Makefile.am (check_PROGRAMS): Likewise. (TESTS): Add execve-v.test and execveat-v.test. (EXTRA_DIST): Remove execve.expected, execve-v.expected, execveat.expected, and execveat-v.expected.
This commit is contained in:
parent
3c00e63b03
commit
23168c1e54
2
tests/.gitignore
vendored
2
tests/.gitignore
vendored
@ -17,7 +17,9 @@ clock_xettime
|
||||
epoll_create1
|
||||
eventfd
|
||||
execve
|
||||
execve-v
|
||||
execveat
|
||||
execveat-v
|
||||
fanotify_mark
|
||||
fcntl
|
||||
fcntl64
|
||||
|
@ -67,7 +67,9 @@ check_PROGRAMS = \
|
||||
epoll_create1 \
|
||||
eventfd \
|
||||
execve \
|
||||
execve-v \
|
||||
execveat \
|
||||
execveat-v \
|
||||
fanotify_mark \
|
||||
fcntl \
|
||||
fcntl64 \
|
||||
@ -211,7 +213,9 @@ TESTS = \
|
||||
epoll_create1.test \
|
||||
eventfd.test \
|
||||
execve.test \
|
||||
execve-v.test \
|
||||
execveat.test \
|
||||
execveat-v.test \
|
||||
fanotify_mark.test \
|
||||
fcntl.test \
|
||||
fcntl64.test \
|
||||
@ -328,10 +332,6 @@ EXTRA_DIST = init.sh run.sh match.awk \
|
||||
caps.awk \
|
||||
dumpio.expected \
|
||||
eventfd.expected \
|
||||
execve.expected \
|
||||
execve-v.expected \
|
||||
execveat.expected \
|
||||
execveat-v.expected \
|
||||
fanotify_mark.expected \
|
||||
filter-unavailable.expected \
|
||||
fstatat.c \
|
||||
|
3
tests/execve-v.c
Normal file
3
tests/execve-v.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* This file is part of execve-v strace test. */
|
||||
#define VERBOSE_EXECVE
|
||||
#include "execve.c"
|
@ -1 +0,0 @@
|
||||
execve\("execve\\nfilename", \["execve\\nfilename", "first", "second"\], \["foobar=1", "foo\\nbar=2"\]\) += -1 ENOENT .*
|
18
tests/execve-v.test
Executable file
18
tests/execve-v.test
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Check verbose decoding of execve syscall.
|
||||
|
||||
. "${srcdir=.}/init.sh"
|
||||
|
||||
check_prog grep
|
||||
run_prog > /dev/null
|
||||
|
||||
OUT="$LOG.out"
|
||||
EXP="$LOG.exp"
|
||||
run_strace -veexecve $args > "$EXP"
|
||||
|
||||
# Filter out execve() call made by strace.
|
||||
grep -F test.execve < "$LOG" > "$OUT"
|
||||
match_diff "$OUT" "$EXP"
|
||||
|
||||
rm -f "$EXP" "$OUT"
|
149
tests/execve.c
149
tests/execve.c
@ -1,5 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
|
||||
* This file is part of execve strace test.
|
||||
*
|
||||
* Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -25,17 +27,150 @@
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "tests.h"
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define FILENAME "execve\nfilename"
|
||||
static const char * const argv[] =
|
||||
{ FILENAME, "first", "second", NULL, NULL, NULL };
|
||||
static const char * const envp[] =
|
||||
{ "foobar=1", "foo\nbar=2", NULL , "", NULL , "", NULL, NULL};
|
||||
#define FILENAME "test.execve\nfilename"
|
||||
#define Q_FILENAME "test.execve\\nfilename"
|
||||
|
||||
static const char * const argv[] = {
|
||||
FILENAME, "first", "second", (const char *) -1L,
|
||||
(const char *) -2L, (const char *) -3L
|
||||
};
|
||||
static const char * const q_argv[] = {
|
||||
Q_FILENAME, "first", "second"
|
||||
};
|
||||
|
||||
static const char * const envp[] = {
|
||||
"foobar=1", "foo\nbar=2", (const char *) -1L,
|
||||
(const char *) -2L, (const char *) -3L
|
||||
};
|
||||
static const char * const q_envp[] = {
|
||||
"foobar=1", "foo\\nbar=2"
|
||||
};
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
execve(FILENAME, (char * const *) argv, (char * const *) envp);
|
||||
char ** const tail_argv = tail_memdup(argv, sizeof(argv));
|
||||
char ** const tail_envp = tail_memdup(envp, sizeof(envp));
|
||||
|
||||
execve(FILENAME, tail_argv, tail_envp);
|
||||
printf("execve(\"%s\""
|
||||
", [\"%s\", \"%s\", \"%s\", %p, %p, %p, ???]"
|
||||
#ifdef VERBOSE_EXECVE
|
||||
", [\"%s\", \"%s\", %p, %p, %p, ???]"
|
||||
#else
|
||||
", [/* 5 vars, unterminated */]"
|
||||
#endif
|
||||
") = -1 %s (%m)\n",
|
||||
Q_FILENAME, q_argv[0], q_argv[1], q_argv[2],
|
||||
argv[3], argv[4], argv[5],
|
||||
#ifdef VERBOSE_EXECVE
|
||||
q_envp[0], q_envp[1], envp[2], envp[3], envp[4],
|
||||
#endif
|
||||
errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
tail_argv[ARRAY_SIZE(q_argv)] = NULL;
|
||||
tail_envp[ARRAY_SIZE(q_envp)] = NULL;
|
||||
|
||||
execve(FILENAME, tail_argv, tail_envp);
|
||||
printf("execve(\"%s\", [\"%s\", \"%s\", \"%s\"]"
|
||||
#ifdef VERBOSE_EXECVE
|
||||
", [\"%s\", \"%s\"]"
|
||||
#else
|
||||
", [/* 2 vars */]"
|
||||
#endif
|
||||
") = -1 %s (%m)\n",
|
||||
Q_FILENAME, q_argv[0], q_argv[1], q_argv[2],
|
||||
#ifdef VERBOSE_EXECVE
|
||||
q_envp[0], q_envp[1],
|
||||
#endif
|
||||
errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
execve(FILENAME, tail_argv + 2, tail_envp + 1);
|
||||
printf("execve(\"%s\", [\"%s\"]"
|
||||
#ifdef VERBOSE_EXECVE
|
||||
", [\"%s\"]"
|
||||
#else
|
||||
", [/* 1 var */]"
|
||||
#endif
|
||||
") = -1 %s (%m)\n",
|
||||
Q_FILENAME, q_argv[2],
|
||||
#ifdef VERBOSE_EXECVE
|
||||
q_envp[1],
|
||||
#endif
|
||||
errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
char **const empty = tail_alloc(sizeof(*empty));
|
||||
*empty = NULL;
|
||||
|
||||
execve(FILENAME, empty, empty);
|
||||
printf("execve(\"%s\", []"
|
||||
#ifdef VERBOSE_EXECVE
|
||||
", []"
|
||||
#else
|
||||
", [/* 0 vars */]"
|
||||
#endif
|
||||
") = -1 %s (%m)\n",
|
||||
Q_FILENAME, errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
char str_a[] = "012345678901234567890123456789012";
|
||||
char str_b[] = "_abcdefghijklmnopqrstuvwxyz()[]{}";
|
||||
#define DEFAULT_STRLEN ((unsigned int) sizeof(str_a) - 2)
|
||||
char **const a = tail_alloc(sizeof(*a) * (DEFAULT_STRLEN + 2));
|
||||
char **const b = tail_alloc(sizeof(*b) * (DEFAULT_STRLEN + 2));
|
||||
unsigned int i;
|
||||
for (i = 0; i <= DEFAULT_STRLEN; ++i) {
|
||||
a[i] = &str_a[i];
|
||||
b[i] = &str_b[i];
|
||||
}
|
||||
a[i] = b[i] = NULL;
|
||||
|
||||
execve(FILENAME, a, b);
|
||||
printf("execve(\"%s\", [\"%.*s\"...", Q_FILENAME, DEFAULT_STRLEN, a[0]);
|
||||
for (i = 1; i < DEFAULT_STRLEN; ++i)
|
||||
printf(", \"%s\"", a[i]);
|
||||
#ifdef VERBOSE_EXECVE
|
||||
printf(", \"%s\"", a[i]);
|
||||
#else
|
||||
printf(", ...");
|
||||
#endif
|
||||
#ifdef VERBOSE_EXECVE
|
||||
printf("], [\"%.*s\"...", DEFAULT_STRLEN, b[0]);
|
||||
for (i = 1; i <= DEFAULT_STRLEN; ++i)
|
||||
printf(", \"%s\"", b[i]);
|
||||
#else
|
||||
printf("], [/* %u vars */", DEFAULT_STRLEN + 1);
|
||||
#endif
|
||||
printf("]) = -1 %s (%m)\n", errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
execve(FILENAME, a + 1, b + 1);
|
||||
printf("execve(\"%s\", [\"%s\"", Q_FILENAME, a[1]);
|
||||
for (i = 2; i <= DEFAULT_STRLEN; ++i)
|
||||
printf(", \"%s\"", a[i]);
|
||||
#ifdef VERBOSE_EXECVE
|
||||
printf("], [\"%s\"", b[1]);
|
||||
for (i = 2; i <= DEFAULT_STRLEN; ++i)
|
||||
printf(", \"%s\"", b[i]);
|
||||
#else
|
||||
printf("], [/* %d vars */", DEFAULT_STRLEN);
|
||||
#endif
|
||||
printf("]) = -1 %s (%m)\n", errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
const void * const efault = tail_alloc(0);
|
||||
|
||||
execve(FILENAME, (char **) tail_argv[ARRAY_SIZE(q_argv)], efault);
|
||||
printf("execve(\"%s\", NULL, %p"
|
||||
") = -1 %s (%m)\n",
|
||||
Q_FILENAME, efault, errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
execve(FILENAME, efault, NULL);
|
||||
printf("execve(\"%s\", %p, NULL"
|
||||
") = -1 %s (%m)\n",
|
||||
Q_FILENAME, efault, errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
execve\("execve\\nfilename", \["execve\\nfilename", "first", "second"\], \[/\* 2 vars \*/\]\) += -1 ENOENT .*
|
@ -4,10 +4,15 @@
|
||||
|
||||
. "${srcdir=.}/init.sh"
|
||||
|
||||
run_prog
|
||||
run_strace $args
|
||||
match_grep
|
||||
run_strace -v $args
|
||||
match_grep "$LOG" "$srcdir/${ME_%.test}-v.expected"
|
||||
check_prog grep
|
||||
run_prog > /dev/null
|
||||
|
||||
exit 0
|
||||
OUT="$LOG.out"
|
||||
EXP="$LOG.exp"
|
||||
run_strace -eexecve $args > "$EXP"
|
||||
|
||||
# Filter out execve() call made by strace.
|
||||
grep -F test.execve < "$LOG" > "$OUT"
|
||||
match_diff "$OUT" "$EXP"
|
||||
|
||||
rm -f "$EXP" "$OUT"
|
||||
|
3
tests/execveat-v.c
Normal file
3
tests/execveat-v.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* This file is part of execveat-v strace test. */
|
||||
#define VERBOSE_EXECVEAT
|
||||
#include "execveat.c"
|
@ -1 +0,0 @@
|
||||
execveat\(AT_FDCWD, "execveat\\nfilename", \["execveat\\nfilename", "first", "second"\], \["foobar=1", "foo\\nbar=2"\], AT_SYMLINK_NOFOLLOW\|AT_EMPTY_PATH\) += -1 .*
|
11
tests/execveat-v.test
Executable file
11
tests/execveat-v.test
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Check verbose decoding of execveat syscall.
|
||||
|
||||
. "${srcdir=.}/init.sh"
|
||||
|
||||
run_prog > /dev/null
|
||||
OUT="$LOG.out"
|
||||
run_strace -veexecveat $args > "$OUT"
|
||||
match_diff "$LOG" "$OUT"
|
||||
rm -f "$OUT"
|
149
tests/execveat.c
149
tests/execveat.c
@ -1,4 +1,6 @@
|
||||
/*
|
||||
* This file is part of execveat strace test.
|
||||
*
|
||||
* Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -26,21 +28,156 @@
|
||||
*/
|
||||
|
||||
#include "tests.h"
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#ifdef __NR_execveat
|
||||
|
||||
#define FILENAME "execveat\nfilename"
|
||||
static const char * const argv[] =
|
||||
{ FILENAME, "first", "second", NULL, NULL, NULL };
|
||||
static const char * const envp[] =
|
||||
{ "foobar=1", "foo\nbar=2", NULL , "", NULL , "", NULL, NULL};
|
||||
# define FILENAME "test.execveat\nfilename"
|
||||
# define Q_FILENAME "test.execveat\\nfilename"
|
||||
|
||||
static const char * const argv[] = {
|
||||
FILENAME, "first", "second", (const char *) -1L,
|
||||
(const char *) -2L, (const char *) -3L
|
||||
};
|
||||
static const char * const q_argv[] = {
|
||||
Q_FILENAME, "first", "second"
|
||||
};
|
||||
|
||||
static const char * const envp[] = {
|
||||
"foobar=1", "foo\nbar=2", (const char *) -1L,
|
||||
(const char *) -2L, (const char *) -3L
|
||||
};
|
||||
static const char * const q_envp[] = {
|
||||
"foobar=1", "foo\\nbar=2"
|
||||
};
|
||||
|
||||
int
|
||||
main(void)
|
||||
{
|
||||
syscall(__NR_execveat, -100, FILENAME, argv, envp, 0x1100);
|
||||
const char ** const tail_argv = tail_memdup(argv, sizeof(argv));
|
||||
const char ** const tail_envp = tail_memdup(envp, sizeof(envp));
|
||||
|
||||
syscall(__NR_execveat, -100, FILENAME, tail_argv, tail_envp, 0x1100);
|
||||
printf("execveat(AT_FDCWD, \"%s\""
|
||||
", [\"%s\", \"%s\", \"%s\", %p, %p, %p, ???]"
|
||||
#ifdef VERBOSE_EXECVEAT
|
||||
", [\"%s\", \"%s\", %p, %p, %p, ???]"
|
||||
#else
|
||||
", [/* 5 vars, unterminated */]"
|
||||
#endif
|
||||
", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
|
||||
Q_FILENAME, q_argv[0], q_argv[1], q_argv[2],
|
||||
argv[3], argv[4], argv[5],
|
||||
#ifdef VERBOSE_EXECVEAT
|
||||
q_envp[0], q_envp[1], envp[2], envp[3], envp[4],
|
||||
#endif
|
||||
errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
tail_argv[ARRAY_SIZE(q_argv)] = NULL;
|
||||
tail_envp[ARRAY_SIZE(q_envp)] = NULL;
|
||||
|
||||
syscall(__NR_execveat, -100, FILENAME, tail_argv, tail_envp, 0x1100);
|
||||
printf("execveat(AT_FDCWD, \"%s\", [\"%s\", \"%s\", \"%s\"]"
|
||||
#ifdef VERBOSE_EXECVEAT
|
||||
", [\"%s\", \"%s\"]"
|
||||
#else
|
||||
", [/* 2 vars */]"
|
||||
#endif
|
||||
", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
|
||||
Q_FILENAME, q_argv[0], q_argv[1], q_argv[2],
|
||||
#ifdef VERBOSE_EXECVEAT
|
||||
q_envp[0], q_envp[1],
|
||||
#endif
|
||||
errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
syscall(__NR_execveat, -100, FILENAME, tail_argv + 2, tail_envp + 1, 0x1100);
|
||||
printf("execveat(AT_FDCWD, \"%s\", [\"%s\"]"
|
||||
#ifdef VERBOSE_EXECVEAT
|
||||
", [\"%s\"]"
|
||||
#else
|
||||
", [/* 1 var */]"
|
||||
#endif
|
||||
", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
|
||||
Q_FILENAME, q_argv[2],
|
||||
#ifdef VERBOSE_EXECVEAT
|
||||
q_envp[1],
|
||||
#endif
|
||||
errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
const char **const empty = tail_alloc(sizeof(*empty));
|
||||
*empty = NULL;
|
||||
|
||||
syscall(__NR_execveat, -100, FILENAME, empty, empty, 0x1100);
|
||||
printf("execveat(AT_FDCWD, \"%s\", []"
|
||||
#ifdef VERBOSE_EXECVEAT
|
||||
", []"
|
||||
#else
|
||||
", [/* 0 vars */]"
|
||||
#endif
|
||||
", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
|
||||
Q_FILENAME, errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
char str_a[] = "012345678901234567890123456789012";
|
||||
char str_b[] = "_abcdefghijklmnopqrstuvwxyz()[]{}";
|
||||
#define DEFAULT_STRLEN ((unsigned int) sizeof(str_a) - 2)
|
||||
char **const a = tail_alloc(sizeof(*a) * (DEFAULT_STRLEN + 2));
|
||||
char **const b = tail_alloc(sizeof(*b) * (DEFAULT_STRLEN + 2));
|
||||
unsigned int i;
|
||||
for (i = 0; i <= DEFAULT_STRLEN; ++i) {
|
||||
a[i] = &str_a[i];
|
||||
b[i] = &str_b[i];
|
||||
}
|
||||
a[i] = b[i] = NULL;
|
||||
|
||||
syscall(__NR_execveat, -100, FILENAME, a, b, 0x1100);
|
||||
printf("execveat(AT_FDCWD, \"%s\", [\"%.*s\"...", Q_FILENAME, DEFAULT_STRLEN, a[0]);
|
||||
for (i = 1; i < DEFAULT_STRLEN; ++i)
|
||||
printf(", \"%s\"", a[i]);
|
||||
#ifdef VERBOSE_EXECVEAT
|
||||
printf(", \"%s\"", a[i]);
|
||||
#else
|
||||
printf(", ...");
|
||||
#endif
|
||||
#ifdef VERBOSE_EXECVEAT
|
||||
printf("], [\"%.*s\"...", DEFAULT_STRLEN, b[0]);
|
||||
for (i = 1; i <= DEFAULT_STRLEN; ++i)
|
||||
printf(", \"%s\"", b[i]);
|
||||
#else
|
||||
printf("], [/* %u vars */", DEFAULT_STRLEN + 1);
|
||||
#endif
|
||||
printf("], AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
|
||||
errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
syscall(__NR_execveat, -100, FILENAME, a + 1, b + 1, 0x1100);
|
||||
printf("execveat(AT_FDCWD, \"%s\", [\"%s\"", Q_FILENAME, a[1]);
|
||||
for (i = 2; i <= DEFAULT_STRLEN; ++i)
|
||||
printf(", \"%s\"", a[i]);
|
||||
#ifdef VERBOSE_EXECVEAT
|
||||
printf("], [\"%s\"", b[1]);
|
||||
for (i = 2; i <= DEFAULT_STRLEN; ++i)
|
||||
printf(", \"%s\"", b[i]);
|
||||
#else
|
||||
printf("], [/* %d vars */", DEFAULT_STRLEN);
|
||||
#endif
|
||||
printf("], AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
|
||||
errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
const void * const efault = tail_alloc(0);
|
||||
|
||||
syscall(__NR_execveat, -100, FILENAME, NULL, efault, 0x1100);
|
||||
printf("execveat(AT_FDCWD, \"%s\", NULL, %p"
|
||||
", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
|
||||
Q_FILENAME, efault, errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
syscall(__NR_execveat, -100, FILENAME, efault, NULL, 0x1100);
|
||||
printf("execveat(AT_FDCWD, \"%s\", %p, NULL"
|
||||
", AT_SYMLINK_NOFOLLOW|AT_EMPTY_PATH) = -1 %s (%m)\n",
|
||||
Q_FILENAME, efault, errno == ENOSYS ? "ENOSYS" : "ENOENT");
|
||||
|
||||
puts("+++ exited with 0 +++");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1 +0,0 @@
|
||||
execveat\(AT_FDCWD, "execveat\\nfilename", \["execveat\\nfilename", "first", "second"\], \[/\* 2 vars \*/\], AT_SYMLINK_NOFOLLOW\|AT_EMPTY_PATH\) += -1 .*
|
@ -4,10 +4,8 @@
|
||||
|
||||
. "${srcdir=.}/init.sh"
|
||||
|
||||
run_prog
|
||||
run_strace $args
|
||||
match_grep
|
||||
run_strace -v $args
|
||||
match_grep "$LOG" "$srcdir/${ME_%.test}-v.expected"
|
||||
|
||||
exit 0
|
||||
run_prog > /dev/null
|
||||
OUT="$LOG.out"
|
||||
run_strace -eexecveat $args > "$OUT"
|
||||
match_diff "$LOG" "$OUT"
|
||||
rm -f "$OUT"
|
||||
|
Loading…
x
Reference in New Issue
Block a user