selinux: fix case of names with whitespace/multibytes on /selinux/create
I submit the patch again, according to patch submission convension. This patch enables to accept percent-encoded object names as forth argument of /selinux/create interface to avoid possible bugs when we give an object name including whitespace or multibutes. E.g) if and when a userspace object manager tries to create a new object named as "resolve.conf but fake", it shall give this name as the forth argument of the /selinux/create. But sscanf() logic in kernel space fetches only the part earlier than the first whitespace. In this case, selinux may unexpectedly answer a default security context configured to "resolve.conf", but it is bug. Although I could not test this patch on named TYPE_TRANSITION rules actually, But debug printk() message seems to me the logic works correctly. I assume the libselinux provides an interface to apply this logic transparently, so nothing shall not be changed from the viewpoint of application. Signed-off-by: KaiGai Kohei <kohei.kaigai@emea.nec.com> Signed-off-by: Eric Paris <eparis@redhat.com>
This commit is contained in:
parent
ea77f7a2e8
commit
0f7e4c33eb
@ -29,6 +29,7 @@
|
|||||||
#include <linux/audit.h>
|
#include <linux/audit.h>
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
#include <linux/kobject.h>
|
#include <linux/kobject.h>
|
||||||
|
#include <linux/ctype.h>
|
||||||
|
|
||||||
/* selinuxfs pseudo filesystem for exporting the security policy API.
|
/* selinuxfs pseudo filesystem for exporting the security policy API.
|
||||||
Based on the proc code and the fs/nfsd/nfsctl.c code. */
|
Based on the proc code and the fs/nfsd/nfsctl.c code. */
|
||||||
@ -751,6 +752,14 @@ out:
|
|||||||
return length;
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int hexcode_to_int(int code) {
|
||||||
|
if (code == '\0' || !isxdigit(code))
|
||||||
|
return -1;
|
||||||
|
if (isdigit(code))
|
||||||
|
return code - '0';
|
||||||
|
return tolower(code) - 'a' + 10;
|
||||||
|
}
|
||||||
|
|
||||||
static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
|
static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
|
||||||
{
|
{
|
||||||
char *scon = NULL, *tcon = NULL;
|
char *scon = NULL, *tcon = NULL;
|
||||||
@ -785,8 +794,34 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
|
|||||||
nargs = sscanf(buf, "%s %s %hu %s", scon, tcon, &tclass, namebuf);
|
nargs = sscanf(buf, "%s %s %hu %s", scon, tcon, &tclass, namebuf);
|
||||||
if (nargs < 3 || nargs > 4)
|
if (nargs < 3 || nargs > 4)
|
||||||
goto out;
|
goto out;
|
||||||
if (nargs == 4)
|
if (nargs == 4) {
|
||||||
|
/*
|
||||||
|
* If and when the name of new object to be queried contains
|
||||||
|
* either whitespace or multibyte characters, they shall be
|
||||||
|
* encoded based on the percentage-encoding rule.
|
||||||
|
* If not encoded, the sscanf logic picks up only left-half
|
||||||
|
* of the supplied name; splitted by a whitespace unexpectedly.
|
||||||
|
*/
|
||||||
|
char *r, *w;
|
||||||
|
int c1, c2;
|
||||||
|
|
||||||
|
r = w = namebuf;
|
||||||
|
do {
|
||||||
|
c1 = *r++;
|
||||||
|
if (c1 == '+')
|
||||||
|
c1 = ' ';
|
||||||
|
else if (c1 == '%') {
|
||||||
|
if ((c1 = hexcode_to_int(*r++)) < 0)
|
||||||
|
goto out;
|
||||||
|
if ((c2 = hexcode_to_int(*r++)) < 0)
|
||||||
|
goto out;
|
||||||
|
c1 = (c1 << 4) | c2;
|
||||||
|
}
|
||||||
|
*w++ = c1;
|
||||||
|
} while (c1 != '\0');
|
||||||
|
|
||||||
objname = namebuf;
|
objname = namebuf;
|
||||||
|
}
|
||||||
|
|
||||||
length = security_context_to_sid(scon, strlen(scon) + 1, &ssid);
|
length = security_context_to_sid(scon, strlen(scon) + 1, &ssid);
|
||||||
if (length)
|
if (length)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user