mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 10:31:33 -04:00
Merge tag 'Smack-for-7.3' of https://github.com/cschaufler/smack-next
Pull smack updates from Casey Schaufler: - Spelling fix - Code optimization in smackfs - Fix credential mis-uses - Place limits on two of the smackfs interfaces * tag 'Smack-for-7.3' of https://github.com/cschaufler/smack-next: smack: fix cred UAF in smack_file_send_sigiotask() smack: restrict smackfs/{direct,mapped} values to 0-255 smack: deduplicate smackfs/{direct,mapped} file_operations smack: show msgrcv() subject task in audit smack: fix incorrect task context in smack_msg_queue_msgrcv security: smack: fix spelling mistake smack: simplify write handlers of sysfs entries Smack: Fix error in capability bypass
This commit is contained in:
@@ -261,6 +261,7 @@ struct smack_audit_data {
|
||||
char *subject;
|
||||
char *object;
|
||||
char *request;
|
||||
struct task_struct *subj_tsk;
|
||||
int result;
|
||||
};
|
||||
|
||||
@@ -317,8 +318,9 @@ int smack_populate_secattr(struct smack_known *skp);
|
||||
* Shared data.
|
||||
*/
|
||||
extern int smack_enabled __initdata;
|
||||
extern int smack_cipso_direct;
|
||||
extern int smack_cipso_mapped;
|
||||
extern u8 smack_cipso_auto_level[2];
|
||||
#define smack_cipso_direct (+smack_cipso_auto_level[0])
|
||||
#define smack_cipso_mapped (+smack_cipso_auto_level[1])
|
||||
extern struct smack_known *smack_net_ambient;
|
||||
extern struct smack_known *smack_syslog_label;
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
|
||||
@@ -331,6 +331,15 @@ static void smack_log_callback(struct audit_buffer *ab, void *a)
|
||||
audit_log_format(ab, " labels_differ");
|
||||
else
|
||||
audit_log_format(ab, " requested=%s", sad->request);
|
||||
|
||||
if (sad->subj_tsk) {
|
||||
char comm[TASK_COMM_LEN];
|
||||
|
||||
audit_log_format(ab, " subj_pid=%d subj_comm=",
|
||||
task_tgid_nr(sad->subj_tsk));
|
||||
audit_log_untrustedstring(ab,
|
||||
get_task_comm(comm, sad->subj_tsk));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -130,12 +130,13 @@ static int smk_bu_note(char *note, struct smack_known *sskp,
|
||||
#define smk_bu_note(note, sskp, oskp, mode, RC) (RC)
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
static int smk_bu_current(char *note, struct smack_known *oskp,
|
||||
int mode, int rc)
|
||||
static int
|
||||
smk_bu_tsk_to_obj(struct task_struct *tsk, const struct task_smack *tsp,
|
||||
char *note, struct smack_known *oskp, int mode, int rc)
|
||||
{
|
||||
struct task_smack *tsp = smack_cred(current_cred());
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
char acc[SMK_NUM_ACCESS_TYPE + 1];
|
||||
char comm[TASK_COMM_LEN];
|
||||
|
||||
if (rc <= 0)
|
||||
return rc;
|
||||
@@ -143,14 +144,22 @@ static int smk_bu_current(char *note, struct smack_known *oskp,
|
||||
rc = 0;
|
||||
|
||||
smk_bu_mode(mode, acc);
|
||||
|
||||
pr_info("Smack %s: (%s %s %s) %s %s\n", smk_bu_mess[rc],
|
||||
tsp->smk_task->smk_known, oskp->smk_known,
|
||||
acc, current->comm, note);
|
||||
smk_of_task(tsp)->smk_known, oskp->smk_known,
|
||||
acc, get_task_comm(comm, tsk), note);
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#define smk_bu_current(note, oskp, mode, RC) (RC)
|
||||
return rc;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int smk_bu_current(char *note, struct smack_known *oskp,
|
||||
int mode, int rc)
|
||||
{
|
||||
return smk_bu_tsk_to_obj(current, smack_cred(current_cred()),
|
||||
note, oskp, mode, rc);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
static int smk_bu_task(struct task_struct *otp, int mode, int rc)
|
||||
@@ -1312,7 +1321,7 @@ static int smack_inode_getattr(const struct path *path)
|
||||
*/
|
||||
static int smack_inode_xattr_skipcap(const char *name)
|
||||
{
|
||||
if (strncmp(name, XATTR_SMACK_SUFFIX, strlen(XATTR_SMACK_SUFFIX)))
|
||||
if (strncmp(name, XATTR_SMACK_SUFFIX, strlen(XATTR_SMACK_SUFFIX)) == 0)
|
||||
return 0;
|
||||
|
||||
if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
|
||||
@@ -1964,7 +1973,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
|
||||
{
|
||||
struct smack_known **blob;
|
||||
struct smack_known *skp;
|
||||
struct smack_known *tkp = smk_of_task(smack_cred(tsk->cred));
|
||||
struct smack_known *tkp = smk_of_task_struct_obj(tsk);
|
||||
const struct cred *tcred;
|
||||
struct file *file;
|
||||
int rc;
|
||||
@@ -3348,14 +3357,20 @@ static int smack_sem_semop(struct kern_ipc_perm *isp, struct sembuf *sops,
|
||||
}
|
||||
|
||||
/**
|
||||
* smk_curacc_msq : helper to check if current has access on msq
|
||||
* @isp : the msq
|
||||
* smk_tskacc_msq : helper to check if tsk has access on msq
|
||||
* @tsk: the task that requests access
|
||||
* @isp : the sysv msg queue permissions
|
||||
* @access : access requested
|
||||
*
|
||||
* return 0 if current has access, error otherwise
|
||||
* return 0 if tsk has access, error otherwise
|
||||
*/
|
||||
static int smk_curacc_msq(struct kern_ipc_perm *isp, int access)
|
||||
static int
|
||||
smk_tskacc_msq(struct task_struct *tsk, struct kern_ipc_perm *isp, int access)
|
||||
{
|
||||
const bool tsk_is_current = (tsk == current);
|
||||
const struct cred * const tsk_cred =
|
||||
(tsk_is_current ? current_cred() : get_task_cred(tsk));
|
||||
struct task_smack * const tsp = smack_cred(tsk_cred);
|
||||
struct smack_known *msp = smack_of_ipc(isp);
|
||||
struct smk_audit_info ad;
|
||||
int rc;
|
||||
@@ -3363,12 +3378,28 @@ static int smk_curacc_msq(struct kern_ipc_perm *isp, int access)
|
||||
#ifdef CONFIG_AUDIT
|
||||
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_IPC);
|
||||
ad.a.u.ipc_id = isp->id;
|
||||
if (!tsk_is_current)
|
||||
ad.sad.subj_tsk = tsk;
|
||||
#endif
|
||||
rc = smk_curacc(msp, access, &ad);
|
||||
rc = smk_bu_current("msq", msp, access, rc);
|
||||
rc = smk_tskacc(tsp, msp, access, &ad);
|
||||
rc = smk_bu_tsk_to_obj(tsk, tsp, "msq", msp, access, rc);
|
||||
if (!tsk_is_current)
|
||||
put_cred(tsk_cred);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* smk_curacc_msq : helper to check if current has access on msq
|
||||
* @isp : the sysv msg queue permissions
|
||||
* @access : access requested
|
||||
*
|
||||
* return 0 if current has access, error otherwise
|
||||
*/
|
||||
static int smk_curacc_msq(struct kern_ipc_perm *isp, int access)
|
||||
{
|
||||
return smk_tskacc_msq(current, isp, access);
|
||||
}
|
||||
|
||||
/**
|
||||
* smack_msg_queue_associate - Smack access check for msg_queue
|
||||
* @isp: the object
|
||||
@@ -3436,21 +3467,21 @@ static int smack_msg_queue_msgsnd(struct kern_ipc_perm *isp, struct msg_msg *msg
|
||||
}
|
||||
|
||||
/**
|
||||
* smack_msg_queue_msgrcv - Smack access check for msg_queue
|
||||
* smack_msg_queue_msgrcv - check it target has r/w access to msg_queue
|
||||
* @isp: the object
|
||||
* @msg: unused
|
||||
* @target: unused
|
||||
* @target: the task that msgrcv() from the queue
|
||||
* @type: unused
|
||||
* @mode: unused
|
||||
*
|
||||
* Returns 0 if current has read and write access, error code otherwise
|
||||
* Returns 0 if target has read and write access, error code otherwise
|
||||
*/
|
||||
static int smack_msg_queue_msgrcv(struct kern_ipc_perm *isp,
|
||||
struct msg_msg *msg,
|
||||
struct task_struct *target, long type,
|
||||
int mode)
|
||||
{
|
||||
return smk_curacc_msq(isp, MAY_READWRITE);
|
||||
return smk_tskacc_msq(target, isp, MAY_READWRITE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -83,18 +83,27 @@ static DEFINE_MUTEX(smk_net6addr_lock);
|
||||
struct smack_known *smack_net_ambient;
|
||||
|
||||
/*
|
||||
* This is the level in a CIPSO header that indicates a
|
||||
* Sensitivity levels for automatically created CIPSO labels.
|
||||
* See smack_access.c`smack_populate_secattr()
|
||||
*
|
||||
* [0] "direct" labeling, label length < SMK_CIPSOLEN(24):
|
||||
* smack label is contained directly in the category set.
|
||||
* It can be reset via smackfs/direct
|
||||
*/
|
||||
int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
|
||||
|
||||
/*
|
||||
* This is the level in a CIPSO header that indicates a
|
||||
*
|
||||
* [1] "mapped" labeling, label length >= SMK_CIPSOLEN(24):
|
||||
* secid is contained directly in the category set.
|
||||
* It can be reset via smackfs/mapped
|
||||
*/
|
||||
int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
|
||||
u8 smack_cipso_auto_level[2] = {
|
||||
SMACK_CIPSO_DIRECT_DEFAULT,
|
||||
SMACK_CIPSO_MAPPED_DEFAULT,
|
||||
};
|
||||
|
||||
static int
|
||||
smk_cipso_auto_level_idx(const struct file *file)
|
||||
{
|
||||
return (file_inode(file)->i_ino != SMK_DIRECT);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURITY_SMACK_BRINGUP
|
||||
/*
|
||||
@@ -115,7 +124,7 @@ struct smack_known *smack_syslog_label;
|
||||
/*
|
||||
* Ptrace current rule
|
||||
* SMACK_PTRACE_DEFAULT regular smack ptrace rules (/proc based)
|
||||
* SMACK_PTRACE_EXACT labels must match, but can be overriden with
|
||||
* SMACK_PTRACE_EXACT labels must match, but can be overridden with
|
||||
* CAP_SYS_PTRACE
|
||||
* SMACK_PTRACE_DRACONIAN labels must match, CAP_SYS_PTRACE has no effect
|
||||
*/
|
||||
@@ -1598,24 +1607,17 @@ static ssize_t smk_read_doi(struct file *filp, char __user *buf,
|
||||
static ssize_t smk_write_doi(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char temp[80];
|
||||
unsigned long u;
|
||||
int ret;
|
||||
u32 u;
|
||||
|
||||
if (!smack_privileged(CAP_MAC_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (count >= sizeof(temp) || count == 0)
|
||||
return -EINVAL;
|
||||
ret = kstrtou32_from_user(buf, count, 10, &u);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
if (copy_from_user(temp, buf, count) != 0)
|
||||
return -EFAULT;
|
||||
|
||||
temp[count] = '\0';
|
||||
|
||||
if (kstrtoul(temp, 10, &u))
|
||||
return -EINVAL;
|
||||
|
||||
if (u == CIPSO_V4_DOI_UNKNOWN || u > U32_MAX)
|
||||
if (u == CIPSO_V4_DOI_UNKNOWN)
|
||||
return -EINVAL;
|
||||
|
||||
return smk_cipso_doi(u, GFP_KERNEL) ? : count;
|
||||
@@ -1628,158 +1630,80 @@ static const struct file_operations smk_doi_ops = {
|
||||
};
|
||||
|
||||
/**
|
||||
* smk_read_direct - read() for /smack/direct
|
||||
* @filp: file pointer, not actually used
|
||||
* smk_read_cipso_auto_level - read() for smackfs/direct and smackfs/mapped
|
||||
* @filp: file pointer
|
||||
* @buf: where to put the result
|
||||
* @count: maximum to send along
|
||||
* @ppos: where to start
|
||||
*
|
||||
* Returns number of bytes read or error code, as appropriate
|
||||
*/
|
||||
static ssize_t smk_read_direct(struct file *filp, char __user *buf,
|
||||
static ssize_t smk_read_cipso_auto_level(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char temp[80];
|
||||
ssize_t rc;
|
||||
char temp[sizeof "255"];
|
||||
int n;
|
||||
|
||||
if (*ppos != 0)
|
||||
return 0;
|
||||
|
||||
sprintf(temp, "%d", smack_cipso_direct);
|
||||
rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
|
||||
|
||||
return rc;
|
||||
n = sprintf(temp, "%u", (unsigned int)smack_cipso_auto_level[
|
||||
smk_cipso_auto_level_idx(filp)]);
|
||||
return simple_read_from_buffer(buf, count, ppos, temp, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* smk_write_direct - write() for /smack/direct
|
||||
* @file: file pointer, not actually used
|
||||
* smk_write_cipso_auto_level - write() for smackfs/direct and smackfs/mapped
|
||||
* @filp: file pointer
|
||||
* @buf: where to get the data from
|
||||
* @count: bytes sent
|
||||
* @ppos: where to start
|
||||
*
|
||||
* Returns number of bytes written or error code, as appropriate
|
||||
*/
|
||||
static ssize_t smk_write_direct(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
static ssize_t
|
||||
smk_write_cipso_auto_level(struct file *filp, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct smack_known *skp;
|
||||
char temp[80];
|
||||
int i;
|
||||
int ret, idx;
|
||||
u8 i, old_lvl;
|
||||
|
||||
if (!smack_privileged(CAP_MAC_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (count >= sizeof(temp) || count == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(temp, buf, count) != 0)
|
||||
return -EFAULT;
|
||||
|
||||
temp[count] = '\0';
|
||||
|
||||
if (sscanf(temp, "%d", &i) != 1)
|
||||
return -EINVAL;
|
||||
/*
|
||||
* draft-ietf-cipso-ipsecurity-01 (CIPSO 2.2), 3.4.2.4:
|
||||
* "Sensitivity Level is 1 octet in length. Its value is from 0 to 255"
|
||||
*/
|
||||
ret = kstrtou8_from_user(buf, count, 10, &i);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Don't do anything if the value hasn't actually changed.
|
||||
* If it is changing reset the level on entries that were
|
||||
* set up to be direct when they were created.
|
||||
* set up to be "auto" level when they were created.
|
||||
*/
|
||||
if (smack_cipso_direct != i) {
|
||||
idx = smk_cipso_auto_level_idx(filp);
|
||||
old_lvl = smack_cipso_auto_level[idx];
|
||||
|
||||
if (old_lvl != i) {
|
||||
struct smack_known *skp;
|
||||
mutex_lock(&smack_known_lock);
|
||||
list_for_each_entry_rcu(skp, &smack_known_list, list)
|
||||
if (skp->smk_netlabel.attr.mls.lvl ==
|
||||
smack_cipso_direct)
|
||||
old_lvl)
|
||||
skp->smk_netlabel.attr.mls.lvl = i;
|
||||
smack_cipso_direct = i;
|
||||
smack_cipso_auto_level[idx] = i;
|
||||
mutex_unlock(&smack_known_lock);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations smk_direct_ops = {
|
||||
.read = smk_read_direct,
|
||||
.write = smk_write_direct,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
/**
|
||||
* smk_read_mapped - read() for /smack/mapped
|
||||
* @filp: file pointer, not actually used
|
||||
* @buf: where to put the result
|
||||
* @count: maximum to send along
|
||||
* @ppos: where to start
|
||||
*
|
||||
* Returns number of bytes read or error code, as appropriate
|
||||
*/
|
||||
static ssize_t smk_read_mapped(struct file *filp, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char temp[80];
|
||||
ssize_t rc;
|
||||
|
||||
if (*ppos != 0)
|
||||
return 0;
|
||||
|
||||
sprintf(temp, "%d", smack_cipso_mapped);
|
||||
rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* smk_write_mapped - write() for /smack/mapped
|
||||
* @file: file pointer, not actually used
|
||||
* @buf: where to get the data from
|
||||
* @count: bytes sent
|
||||
* @ppos: where to start
|
||||
*
|
||||
* Returns number of bytes written or error code, as appropriate
|
||||
*/
|
||||
static ssize_t smk_write_mapped(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct smack_known *skp;
|
||||
char temp[80];
|
||||
int i;
|
||||
|
||||
if (!smack_privileged(CAP_MAC_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (count >= sizeof(temp) || count == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (copy_from_user(temp, buf, count) != 0)
|
||||
return -EFAULT;
|
||||
|
||||
temp[count] = '\0';
|
||||
|
||||
if (sscanf(temp, "%d", &i) != 1)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Don't do anything if the value hasn't actually changed.
|
||||
* If it is changing reset the level on entries that were
|
||||
* set up to be mapped when they were created.
|
||||
*/
|
||||
if (smack_cipso_mapped != i) {
|
||||
mutex_lock(&smack_known_lock);
|
||||
list_for_each_entry_rcu(skp, &smack_known_list, list)
|
||||
if (skp->smk_netlabel.attr.mls.lvl ==
|
||||
smack_cipso_mapped)
|
||||
skp->smk_netlabel.attr.mls.lvl = i;
|
||||
smack_cipso_mapped = i;
|
||||
mutex_unlock(&smack_known_lock);
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations smk_mapped_ops = {
|
||||
.read = smk_read_mapped,
|
||||
.write = smk_write_mapped,
|
||||
static const struct file_operations
|
||||
smk_cipso_auto_level_ops = {
|
||||
.read = smk_read_cipso_auto_level,
|
||||
.write = smk_write_cipso_auto_level,
|
||||
.llseek = default_llseek,
|
||||
};
|
||||
|
||||
@@ -2179,22 +2103,15 @@ static ssize_t smk_read_logging(struct file *filp, char __user *buf,
|
||||
static ssize_t smk_write_logging(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char temp[32];
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
if (!smack_privileged(CAP_MAC_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (count >= sizeof(temp) || count == 0)
|
||||
return -EINVAL;
|
||||
ret = kstrtos32_from_user(buf, count, 10, &i);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
if (copy_from_user(temp, buf, count) != 0)
|
||||
return -EFAULT;
|
||||
|
||||
temp[count] = '\0';
|
||||
|
||||
if (sscanf(temp, "%d", &i) != 1)
|
||||
return -EINVAL;
|
||||
if (i < 0 || i > 3)
|
||||
return -EINVAL;
|
||||
log_policy = i;
|
||||
@@ -2838,22 +2755,15 @@ static ssize_t smk_read_ptrace(struct file *filp, char __user *buf,
|
||||
static ssize_t smk_write_ptrace(struct file *file, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
char temp[32];
|
||||
int i;
|
||||
int i, ret;
|
||||
|
||||
if (!smack_privileged(CAP_MAC_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (*ppos != 0 || count >= sizeof(temp) || count == 0)
|
||||
return -EINVAL;
|
||||
ret = kstrtos32_from_user(buf, count, 10, &i);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
|
||||
if (copy_from_user(temp, buf, count) != 0)
|
||||
return -EFAULT;
|
||||
|
||||
temp[count] = '\0';
|
||||
|
||||
if (sscanf(temp, "%d", &i) != 1)
|
||||
return -EINVAL;
|
||||
if (i < SMACK_PTRACE_DEFAULT || i > SMACK_PTRACE_MAX)
|
||||
return -EINVAL;
|
||||
smack_ptrace_rule = i;
|
||||
@@ -2888,7 +2798,7 @@ static int smk_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
[SMK_DOI] = {
|
||||
"doi", &smk_doi_ops, S_IRUGO|S_IWUSR},
|
||||
[SMK_DIRECT] = {
|
||||
"direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
|
||||
"direct", &smk_cipso_auto_level_ops, 0644},
|
||||
[SMK_AMBIENT] = {
|
||||
"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
|
||||
[SMK_NET4ADDR] = {
|
||||
@@ -2904,7 +2814,7 @@ static int smk_fill_super(struct super_block *sb, struct fs_context *fc)
|
||||
[SMK_ACCESSES] = {
|
||||
"access", &smk_access_ops, S_IRUGO|S_IWUGO},
|
||||
[SMK_MAPPED] = {
|
||||
"mapped", &smk_mapped_ops, S_IRUGO|S_IWUSR},
|
||||
"mapped", &smk_cipso_auto_level_ops, 0644},
|
||||
[SMK_LOAD2] = {
|
||||
"load2", &smk_load2_ops, S_IRUGO|S_IWUSR},
|
||||
[SMK_LOAD_SELF2] = {
|
||||
|
||||
Reference in New Issue
Block a user