Add AT_PLATFORM, AT_HWCAP and AT_CLKTCK auxiliary vector entries which
are used by glibc. This silents the message "2.4+ kernel w/o ELF notes?" from some programs at start, among them are top and pkill. Do the assignment of the vector entries in elf_linux_fixup() as it is done in glibc. Fix some minor style issues. Submitted by: Marcin Cieslak <saper at SYSTEM PL> Approved by: kib (mentor) MFC after: 1 week
This commit is contained in:
parent
09efd0ec6a
commit
4d7c2e8a48
@ -108,6 +108,10 @@ typedef struct {
|
||||
|
||||
#define LINUX_CTL_MAXNAME 10
|
||||
|
||||
#define LINUX_AT_COUNT 16 /* Count of used aux entry types.
|
||||
* Keep this synchronized with
|
||||
* elf_linux_fixup() code.
|
||||
*/
|
||||
struct l___sysctl_args
|
||||
{
|
||||
l_uintptr_t name;
|
||||
|
@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <amd64/linux32/linux32_proto.h>
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_mib.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
#include <compat/linux/linux_signal.h>
|
||||
#include <compat/linux/linux_util.h>
|
||||
|
||||
@ -106,6 +107,8 @@ MALLOC_DEFINE(M_LINUX, "linux", "Linux mode structures");
|
||||
#define LINUX_SYS_linux_rt_sendsig 0
|
||||
#define LINUX_SYS_linux_sendsig 0
|
||||
|
||||
const char *linux_platform = "i686";
|
||||
static int linux_szplatform;
|
||||
extern char linux_sigcode[];
|
||||
extern int linux_szsigcode;
|
||||
|
||||
@ -246,7 +249,12 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
|
||||
{
|
||||
Elf32_Auxargs *args;
|
||||
Elf32_Addr *base;
|
||||
Elf32_Addr *pos;
|
||||
Elf32_Addr *pos, *uplatform;
|
||||
struct linux32_ps_strings *arginfo;
|
||||
|
||||
arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS;
|
||||
uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szsigcode -
|
||||
linux_szplatform);
|
||||
|
||||
KASSERT(curthread->td_proc == imgp->proc,
|
||||
("unsafe elf_linux_fixup(), should be curproc"));
|
||||
@ -254,8 +262,8 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
|
||||
args = (Elf32_Auxargs *)imgp->auxargs;
|
||||
pos = base + (imgp->args->argc + imgp->args->envc + 2);
|
||||
|
||||
if (args->execfd != -1)
|
||||
AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd);
|
||||
AUXARGS_ENTRY_32(pos, LINUX_AT_HWCAP, cpu_feature);
|
||||
AUXARGS_ENTRY_32(pos, LINUX_AT_CLKTCK, hz);
|
||||
AUXARGS_ENTRY_32(pos, AT_PHDR, args->phdr);
|
||||
AUXARGS_ENTRY_32(pos, AT_PHENT, args->phent);
|
||||
AUXARGS_ENTRY_32(pos, AT_PHNUM, args->phnum);
|
||||
@ -263,10 +271,14 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
|
||||
AUXARGS_ENTRY_32(pos, AT_FLAGS, args->flags);
|
||||
AUXARGS_ENTRY_32(pos, AT_ENTRY, args->entry);
|
||||
AUXARGS_ENTRY_32(pos, AT_BASE, args->base);
|
||||
AUXARGS_ENTRY_32(pos, LINUX_AT_SECURE, 0);
|
||||
AUXARGS_ENTRY_32(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
|
||||
AUXARGS_ENTRY_32(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
|
||||
AUXARGS_ENTRY_32(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
|
||||
AUXARGS_ENTRY_32(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
|
||||
AUXARGS_ENTRY_32(pos, LINUX_AT_PLATFORM, PTROUT(uplatform));
|
||||
if (args->execfd != -1)
|
||||
AUXARGS_ENTRY_32(pos, AT_EXECFD, args->execfd);
|
||||
AUXARGS_ENTRY_32(pos, AT_NULL, 0);
|
||||
|
||||
free(imgp->auxargs, M_TEMP);
|
||||
@ -857,23 +869,27 @@ linux_copyout_strings(struct image_params *imgp)
|
||||
char *stringp, *destp;
|
||||
u_int32_t *stack_base;
|
||||
struct linux32_ps_strings *arginfo;
|
||||
int sigcodesz;
|
||||
|
||||
/*
|
||||
* Calculate string base and vector table pointers.
|
||||
* Also deal with signal trampoline code for this exec type.
|
||||
*/
|
||||
arginfo = (struct linux32_ps_strings *)LINUX32_PS_STRINGS;
|
||||
sigcodesz = *(imgp->proc->p_sysent->sv_szsigcode);
|
||||
destp = (caddr_t)arginfo - sigcodesz - SPARE_USRSPACE -
|
||||
roundup((ARG_MAX - imgp->args->stringspace), sizeof(char *));
|
||||
destp = (caddr_t)arginfo - linux_szsigcode - SPARE_USRSPACE -
|
||||
linux_szplatform - roundup((ARG_MAX - imgp->args->stringspace),
|
||||
sizeof(char *));
|
||||
|
||||
/*
|
||||
* install sigcode
|
||||
*/
|
||||
if (sigcodesz)
|
||||
copyout(imgp->proc->p_sysent->sv_sigcode,
|
||||
((caddr_t)arginfo - sigcodesz), sigcodesz);
|
||||
copyout(imgp->proc->p_sysent->sv_sigcode,
|
||||
((caddr_t)arginfo - linux_szsigcode), linux_szsigcode);
|
||||
|
||||
/*
|
||||
* Install LINUX_PLATFORM
|
||||
*/
|
||||
copyout(linux_platform, ((caddr_t)arginfo - linux_szsigcode -
|
||||
linux_szplatform), linux_szplatform);
|
||||
|
||||
/*
|
||||
* If we have a valid auxargs ptr, prepare some room
|
||||
@ -885,7 +901,7 @@ linux_copyout_strings(struct image_params *imgp)
|
||||
* lower compatibility.
|
||||
*/
|
||||
imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size :
|
||||
(AT_COUNT * 2);
|
||||
(LINUX_AT_COUNT * 2);
|
||||
/*
|
||||
* The '+ 2' is for the null pointers at the end of each of
|
||||
* the arg and env vector sets,and imgp->auxarg_size is room
|
||||
@ -919,14 +935,14 @@ linux_copyout_strings(struct image_params *imgp)
|
||||
/*
|
||||
* Fill in "ps_strings" struct for ps, w, etc.
|
||||
*/
|
||||
suword32(&arginfo->ps_argvstr, (u_int32_t)(intptr_t)vectp);
|
||||
suword32(&arginfo->ps_argvstr, (uint32_t)(intptr_t)vectp);
|
||||
suword32(&arginfo->ps_nargvstr, argc);
|
||||
|
||||
/*
|
||||
* Fill in argument portion of vector table.
|
||||
*/
|
||||
for (; argc > 0; --argc) {
|
||||
suword32(vectp++, (u_int32_t)(intptr_t)destp);
|
||||
suword32(vectp++, (uint32_t)(intptr_t)destp);
|
||||
while (*stringp++ != 0)
|
||||
destp++;
|
||||
destp++;
|
||||
@ -935,14 +951,14 @@ linux_copyout_strings(struct image_params *imgp)
|
||||
/* a null vector table pointer separates the argp's from the envp's */
|
||||
suword32(vectp++, 0);
|
||||
|
||||
suword32(&arginfo->ps_envstr, (u_int32_t)(intptr_t)vectp);
|
||||
suword32(&arginfo->ps_envstr, (uint32_t)(intptr_t)vectp);
|
||||
suword32(&arginfo->ps_nenvstr, envc);
|
||||
|
||||
/*
|
||||
* Fill in environment portion of vector table.
|
||||
*/
|
||||
for (; envc > 0; --envc) {
|
||||
suword32(vectp++, (u_int32_t)(intptr_t)destp);
|
||||
suword32(vectp++, (uint32_t)(intptr_t)destp);
|
||||
while (*stringp++ != 0)
|
||||
destp++;
|
||||
destp++;
|
||||
@ -1089,6 +1105,8 @@ linux_elf_modevent(module_t mod, int type, void *data)
|
||||
linux_schedtail, NULL, 1000);
|
||||
linux_exec_tag = EVENTHANDLER_REGISTER(process_exec,
|
||||
linux_proc_exec, NULL, 1000);
|
||||
linux_szplatform = roundup(strlen(linux_platform) + 1,
|
||||
sizeof(char *));
|
||||
if (bootverbose)
|
||||
printf("Linux ELF exec handler installed\n");
|
||||
} else
|
||||
|
@ -92,10 +92,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
|
||||
#ifdef __i386__
|
||||
#include <machine/cputypes.h>
|
||||
#endif
|
||||
|
||||
#define BSD_TO_LINUX_SIGNAL(sig) \
|
||||
(((sig) <= LINUX_SIGTBLSZ) ? bsd_to_linux_signal[_SIG_IDX(sig)] : sig)
|
||||
|
||||
@ -731,34 +727,8 @@ linux_newuname(struct thread *td, struct linux_newuname_args *args)
|
||||
*p = '\0';
|
||||
break;
|
||||
}
|
||||
#ifdef __i386__
|
||||
{
|
||||
const char *class;
|
||||
strlcpy(utsname.machine, linux_platform, LINUX_MAX_UTSNAME);
|
||||
|
||||
switch (cpu_class) {
|
||||
case CPUCLASS_686:
|
||||
class = "i686";
|
||||
break;
|
||||
case CPUCLASS_586:
|
||||
class = "i586";
|
||||
break;
|
||||
case CPUCLASS_486:
|
||||
class = "i486";
|
||||
break;
|
||||
default:
|
||||
class = "i386";
|
||||
}
|
||||
strlcpy(utsname.machine, class, LINUX_MAX_UTSNAME);
|
||||
}
|
||||
#elif defined(__amd64__) /* XXX: Linux can change 'personality'. */
|
||||
#ifdef COMPAT_LINUX32
|
||||
strlcpy(utsname.machine, "i686", LINUX_MAX_UTSNAME);
|
||||
#else
|
||||
strlcpy(utsname.machine, "x86_64", LINUX_MAX_UTSNAME);
|
||||
#endif /* COMPAT_LINUX32 */
|
||||
#else /* something other than i386 or amd64 - assume we and Linux agree */
|
||||
strlcpy(utsname.machine, machine, LINUX_MAX_UTSNAME);
|
||||
#endif /* __i386__ */
|
||||
mtx_lock(&hostname_mtx);
|
||||
strlcpy(utsname.domainname, V_domainname, LINUX_MAX_UTSNAME);
|
||||
mtx_unlock(&hostname_mtx);
|
||||
|
@ -45,4 +45,19 @@
|
||||
#define LINUX_MREMAP_MAYMOVE 1
|
||||
#define LINUX_MREMAP_FIXED 2
|
||||
|
||||
extern const char *linux_platform;
|
||||
|
||||
/*
|
||||
* Non-standard aux entry types used in Linux ELF binaries.
|
||||
*/
|
||||
|
||||
#define LINUX_AT_PLATFORM 15 /* String identifying CPU */
|
||||
#define LINUX_AT_HWCAP 16 /* CPU capabilities */
|
||||
#define LINUX_AT_CLKTCK 17 /* frequency at which times() increments */
|
||||
#define LINUX_AT_SECURE 23 /* secure mode boolean */
|
||||
#define LINUX_AT_BASE_PLATFORM 24 /* string identifying real platform, may
|
||||
* differ from AT_PLATFORM.
|
||||
*/
|
||||
#define LINUX_AT_EXECFN 31 /* filename of program */
|
||||
|
||||
#endif /* _LINUX_MISC_H_ */
|
||||
|
@ -102,6 +102,10 @@ typedef struct {
|
||||
|
||||
#define LINUX_CTL_MAXNAME 10
|
||||
|
||||
#define LINUX_AT_COUNT 16 /* Count of used aux entry types.
|
||||
* Keep this synchronized with
|
||||
* elf_linux_fixup() code.
|
||||
*/
|
||||
struct l___sysctl_args
|
||||
{
|
||||
l_int *name;
|
||||
|
@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <vm/vm_param.h>
|
||||
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/cputypes.h>
|
||||
#include <machine/md_var.h>
|
||||
#include <machine/pcb.h>
|
||||
|
||||
@ -65,6 +66,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <i386/linux/linux_proto.h>
|
||||
#include <compat/linux/linux_emul.h>
|
||||
#include <compat/linux/linux_mib.h>
|
||||
#include <compat/linux/linux_misc.h>
|
||||
#include <compat/linux/linux_signal.h>
|
||||
#include <compat/linux/linux_util.h>
|
||||
|
||||
@ -107,6 +109,10 @@ static void linux_prepsyscall(struct trapframe *tf, int *args, u_int *code,
|
||||
static void linux_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask);
|
||||
static void exec_linux_setregs(struct thread *td, u_long entry,
|
||||
u_long stack, u_long ps_strings);
|
||||
static register_t *linux_copyout_strings(struct image_params *imgp);
|
||||
|
||||
static int linux_szplatform;
|
||||
const char *linux_platform;
|
||||
|
||||
extern LIST_HEAD(futex_list, futex) futex_list;
|
||||
extern struct sx futex_sx;
|
||||
@ -231,22 +237,30 @@ linux_fixup(register_t **stack_base, struct image_params *imgp)
|
||||
**stack_base = (intptr_t)(void *)argv;
|
||||
(*stack_base)--;
|
||||
**stack_base = imgp->args->argc;
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
|
||||
{
|
||||
struct proc *p;
|
||||
Elf32_Auxargs *args;
|
||||
Elf32_Addr *uplatform;
|
||||
struct ps_strings *arginfo;
|
||||
register_t *pos;
|
||||
|
||||
KASSERT(curthread->td_proc == imgp->proc,
|
||||
("unsafe elf_linux_fixup(), should be curproc"));
|
||||
|
||||
p = imgp->proc;
|
||||
arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
|
||||
uplatform = (Elf32_Addr *)((caddr_t)arginfo - linux_szsigcode -
|
||||
linux_szplatform);
|
||||
args = (Elf32_Auxargs *)imgp->auxargs;
|
||||
pos = *stack_base + (imgp->args->argc + imgp->args->envc + 2);
|
||||
|
||||
if (args->execfd != -1)
|
||||
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_HWCAP, cpu_feature);
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_CLKTCK, hz);
|
||||
AUXARGS_ENTRY(pos, AT_PHDR, args->phdr);
|
||||
AUXARGS_ENTRY(pos, AT_PHENT, args->phent);
|
||||
AUXARGS_ENTRY(pos, AT_PHNUM, args->phnum);
|
||||
@ -254,10 +268,14 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
|
||||
AUXARGS_ENTRY(pos, AT_FLAGS, args->flags);
|
||||
AUXARGS_ENTRY(pos, AT_ENTRY, args->entry);
|
||||
AUXARGS_ENTRY(pos, AT_BASE, args->base);
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_SECURE, 0);
|
||||
AUXARGS_ENTRY(pos, AT_UID, imgp->proc->p_ucred->cr_ruid);
|
||||
AUXARGS_ENTRY(pos, AT_EUID, imgp->proc->p_ucred->cr_svuid);
|
||||
AUXARGS_ENTRY(pos, AT_GID, imgp->proc->p_ucred->cr_rgid);
|
||||
AUXARGS_ENTRY(pos, AT_EGID, imgp->proc->p_ucred->cr_svgid);
|
||||
AUXARGS_ENTRY(pos, LINUX_AT_PLATFORM, PTROUT(uplatform));
|
||||
if (args->execfd != -1)
|
||||
AUXARGS_ENTRY(pos, AT_EXECFD, args->execfd);
|
||||
AUXARGS_ENTRY(pos, AT_NULL, 0);
|
||||
|
||||
free(imgp->auxargs, M_TEMP);
|
||||
@ -265,9 +283,125 @@ elf_linux_fixup(register_t **stack_base, struct image_params *imgp)
|
||||
|
||||
(*stack_base)--;
|
||||
**stack_base = (register_t)imgp->args->argc;
|
||||
return 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copied from kern/kern_exec.c
|
||||
*/
|
||||
static register_t *
|
||||
linux_copyout_strings(struct image_params *imgp)
|
||||
{
|
||||
int argc, envc;
|
||||
char **vectp;
|
||||
char *stringp, *destp;
|
||||
register_t *stack_base;
|
||||
struct ps_strings *arginfo;
|
||||
struct proc *p;
|
||||
|
||||
/*
|
||||
* Calculate string base and vector table pointers.
|
||||
* Also deal with signal trampoline code for this exec type.
|
||||
*/
|
||||
p = imgp->proc;
|
||||
arginfo = (struct ps_strings *)p->p_sysent->sv_psstrings;
|
||||
destp = (caddr_t)arginfo - linux_szsigcode - SPARE_USRSPACE -
|
||||
linux_szplatform - roundup((ARG_MAX - imgp->args->stringspace),
|
||||
sizeof(char *));
|
||||
|
||||
/*
|
||||
* install sigcode
|
||||
*/
|
||||
copyout(p->p_sysent->sv_sigcode, ((caddr_t)arginfo -
|
||||
linux_szsigcode), linux_szsigcode);
|
||||
|
||||
/*
|
||||
* install LINUX_PLATFORM
|
||||
*/
|
||||
copyout(linux_platform, ((caddr_t)arginfo - linux_szsigcode -
|
||||
linux_szplatform), linux_szplatform);
|
||||
|
||||
/*
|
||||
* If we have a valid auxargs ptr, prepare some room
|
||||
* on the stack.
|
||||
*/
|
||||
if (imgp->auxargs) {
|
||||
/*
|
||||
* 'AT_COUNT*2' is size for the ELF Auxargs data. This is for
|
||||
* lower compatibility.
|
||||
*/
|
||||
imgp->auxarg_size = (imgp->auxarg_size) ? imgp->auxarg_size :
|
||||
(LINUX_AT_COUNT * 2);
|
||||
/*
|
||||
* The '+ 2' is for the null pointers at the end of each of
|
||||
* the arg and env vector sets,and imgp->auxarg_size is room
|
||||
* for argument of Runtime loader.
|
||||
*/
|
||||
vectp = (char **)(destp - (imgp->args->argc +
|
||||
imgp->args->envc + 2 + imgp->auxarg_size) * sizeof(char *));
|
||||
} else {
|
||||
/*
|
||||
* The '+ 2' is for the null pointers at the end of each of
|
||||
* the arg and env vector sets
|
||||
*/
|
||||
vectp = (char **)(destp - (imgp->args->argc + imgp->args->envc + 2) *
|
||||
sizeof(char *));
|
||||
}
|
||||
|
||||
/*
|
||||
* vectp also becomes our initial stack base
|
||||
*/
|
||||
stack_base = (register_t *)vectp;
|
||||
|
||||
stringp = imgp->args->begin_argv;
|
||||
argc = imgp->args->argc;
|
||||
envc = imgp->args->envc;
|
||||
|
||||
/*
|
||||
* Copy out strings - arguments and environment.
|
||||
*/
|
||||
copyout(stringp, destp, ARG_MAX - imgp->args->stringspace);
|
||||
|
||||
/*
|
||||
* Fill in "ps_strings" struct for ps, w, etc.
|
||||
*/
|
||||
suword(&arginfo->ps_argvstr, (long)(intptr_t)vectp);
|
||||
suword(&arginfo->ps_nargvstr, argc);
|
||||
|
||||
/*
|
||||
* Fill in argument portion of vector table.
|
||||
*/
|
||||
for (; argc > 0; --argc) {
|
||||
suword(vectp++, (long)(intptr_t)destp);
|
||||
while (*stringp++ != 0)
|
||||
destp++;
|
||||
destp++;
|
||||
}
|
||||
|
||||
/* a null vector table pointer separates the argp's from the envp's */
|
||||
suword(vectp++, 0);
|
||||
|
||||
suword(&arginfo->ps_envstr, (long)(intptr_t)vectp);
|
||||
suword(&arginfo->ps_nenvstr, envc);
|
||||
|
||||
/*
|
||||
* Fill in environment portion of vector table.
|
||||
*/
|
||||
for (; envc > 0; --envc) {
|
||||
suword(vectp++, (long)(intptr_t)destp);
|
||||
while (*stringp++ != 0)
|
||||
destp++;
|
||||
destp++;
|
||||
}
|
||||
|
||||
/* end of vector table is a null pointer */
|
||||
suword(vectp, 0);
|
||||
|
||||
return (stack_base);
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern int _ucodesel, _udatasel;
|
||||
extern unsigned long linux_sznonrtsigcode;
|
||||
|
||||
@ -808,6 +942,25 @@ exec_linux_setregs(struct thread *td, u_long entry,
|
||||
fldcw(&control);
|
||||
}
|
||||
|
||||
static void
|
||||
linux_get_machine(const char **dst)
|
||||
{
|
||||
|
||||
switch (cpu_class) {
|
||||
case CPUCLASS_686:
|
||||
*dst = "i686";
|
||||
break;
|
||||
case CPUCLASS_586:
|
||||
*dst = "i586";
|
||||
break;
|
||||
case CPUCLASS_486:
|
||||
*dst = "i486";
|
||||
break;
|
||||
default:
|
||||
*dst = "i386";
|
||||
}
|
||||
}
|
||||
|
||||
struct sysentvec linux_sysvec = {
|
||||
.sv_size = LINUX_SYS_MAXSYSCALL,
|
||||
.sv_table = linux_sysent,
|
||||
@ -863,7 +1016,7 @@ struct sysentvec elf_linux_sysvec = {
|
||||
.sv_usrstack = USRSTACK,
|
||||
.sv_psstrings = PS_STRINGS,
|
||||
.sv_stackprot = VM_PROT_ALL,
|
||||
.sv_copyout_strings = exec_copyout_strings,
|
||||
.sv_copyout_strings = linux_copyout_strings,
|
||||
.sv_setregs = exec_linux_setregs,
|
||||
.sv_fixlimit = NULL,
|
||||
.sv_maxssiz = NULL,
|
||||
@ -929,6 +1082,9 @@ linux_elf_modevent(module_t mod, int type, void *data)
|
||||
NULL, 1000);
|
||||
linux_exec_tag = EVENTHANDLER_REGISTER(process_exec, linux_proc_exec,
|
||||
NULL, 1000);
|
||||
linux_get_machine(&linux_platform);
|
||||
linux_szplatform = roundup(strlen(linux_platform) + 1,
|
||||
sizeof(char *));
|
||||
if (bootverbose)
|
||||
printf("Linux ELF exec handler installed\n");
|
||||
} else
|
||||
|
Loading…
x
Reference in New Issue
Block a user