Пример #1
0
int cap_set_file(const char *filename, cap_t cap_d)
{
    struct vfs_cap_data rawvfscap;
    int sizeofcaps;
    struct stat buf;

    if (lstat(filename, &buf) != 0) {
	_cap_debug("unable to stat file [%s]", filename);
	return -1;
    }
    if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
	_cap_debug("file [%s] is not a regular file", filename);
	errno = EINVAL;
	return -1;
    }

    if (cap_d == NULL) {
	_cap_debug("removing filename capabilities");
	return removexattr(filename, XATTR_NAME_CAPS);
    } else if (_fcaps_save(&rawvfscap, cap_d, &sizeofcaps) != 0) {
	return -1;
    }

    _cap_debug("setting filename capabilities");
    return setxattr(filename, XATTR_NAME_CAPS, &rawvfscap, sizeofcaps, 0);
}
Пример #2
0
int cap_set_fd(int fildes, cap_t cap_d)
{
    struct vfs_cap_data rawvfscap;
    int sizeofcaps;
    struct stat buf;

    if (fstat(fildes, &buf) != 0) {
	_cap_debug("unable to stat file descriptor %d", fildes);
	return -1;
    }
    if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
	_cap_debug("file descriptor %d for non-regular file", fildes);
	errno = EINVAL;
	return -1;
    }

    if (cap_d == NULL) {
	_cap_debug("deleting fildes capabilities");
	return fremovexattr(fildes, XATTR_NAME_CAPS);
    } else if (_fcaps_save(&rawvfscap, cap_d, &sizeofcaps) != 0) {
	return -1;
    }

    _cap_debug("setting fildes capabilities");

    return fsetxattr(fildes, XATTR_NAME_CAPS, &rawvfscap, sizeofcaps, 0);
}
Пример #3
0
cap_t cap_get_file(const char *filename)
{
    cap_t result;

    /* allocate a new capability set */
    result = cap_init();
    if (result) {
	struct vfs_cap_data rawvfscap;
	int sizeofcaps;

	_cap_debug("getting filename capabilities");

	/* fill the capability sets via a system call */
	sizeofcaps = getxattr(filename, XATTR_NAME_CAPS,
			      &rawvfscap, sizeof(rawvfscap));
	if (sizeofcaps < ssizeof(rawvfscap.magic_etc)) {
	    cap_free(result);
	    result = NULL;
	} else {
	    result = _fcaps_load(&rawvfscap, result, sizeofcaps);
	}
    }

    return result;
}
Пример #4
0
cap_t cap_dup(cap_t cap_d)
{
    cap_t result;

    if (!good_cap_t(cap_d)) {
	_cap_debug("bad argument");
	errno = EINVAL;
	return NULL;
    }

    result = cap_init();
    if (result == NULL) {
	_cap_debug("out of memory");
	return NULL;
    }

    memcpy(result, cap_d, sizeof(*cap_d));

    return result;
}
Пример #5
0
int cap_set_file(const char *filename, cap_t cap_d)
{
    if (!good_cap_t(cap_d)) {
	errno = EINVAL;
	return -1;
    }

    _cap_debug("setting filename capabilities");
    return _setfilecap(filename, sizeof(struct __cap_s),
			  &cap_d->set[CAP_INHERITABLE],
			  &cap_d->set[CAP_PERMITTED],
			  &cap_d->set[CAP_EFFECTIVE] );
}
Пример #6
0
int cap_set_proc(cap_t cap_d)
{
    int retval;

    if (!good_cap_t(cap_d)) {
	errno = EINVAL;
	return -1;
    }

    _cap_debug("setting process capabilities");
    retval = capset(&cap_d->head, &cap_d->set);

    cap_d->head.version = _LINUX_CAPABILITY_VERSION;
    return retval;
}
Пример #7
0
int capsetp(pid_t pid, cap_t cap_d)
{
    int error;

    if (!good_cap_t(cap_d)) {
	errno = EINVAL;
	return -1;
    }

    _cap_debug("setting process capabilities for proc %d", pid);
    cap_d->head.pid = pid;
    error = capset(&cap_d->head, &cap_d->set);
    cap_d->head.version = _LINUX_CAPABILITY_VERSION;
    cap_d->head.pid = 0;

    return error;
}
Пример #8
0
cap_t cap_get_proc(void)
{
    cap_t result;

    /* allocate a new capability set */
    result = cap_init();
    if (result) {
	_cap_debug("getting current process' capabilities");

	/* fill the capability sets via a system call */
	if (capget(&result->head, &result->set)) {
	    cap_free(&result);
	}
    }

    return result;
}
Пример #9
0
cap_t cap_get_file(const char *filename)
{
    cap_t result;

    /* allocate a new capability set */
    result = cap_init();
    if (result) {
	_cap_debug("getting named file capabilities");

	/* fill the capability sets via a system call */
	if (_getfilecap(filename, sizeof(struct __cap_s),
			     &result->set[CAP_INHERITABLE],
			     &result->set[CAP_PERMITTED],
			     &result->set[CAP_EFFECTIVE] ))
	    cap_free(&result);
    }

    return result;
}
Пример #10
0
cap_t cap_get_fd(int fildes)
{
    cap_t result;

    /* allocate a new capability set */
    result = cap_init();
    if (result) {
	_cap_debug("getting fildes capabilities");

	/* fill the capability sets via a system call */
	if (_fgetfilecap(fildes, sizeof(struct __cap_s),
			      &result->set[CAP_INHERITABLE],
			      &result->set[CAP_PERMITTED],
			      &result->set[CAP_EFFECTIVE] )) {
	    cap_free(&result);
	}
    }

    return result;
}
Пример #11
0
cap_t cap_init(void)
{
    __u32 *raw_data;
    cap_t result;

    raw_data = malloc( sizeof(__u32) + sizeof(*result) );

    if (raw_data == NULL) {
       _cap_debug("out of memory");
       errno = ENOMEM;
       return NULL;
    }

    *raw_data = CAP_T_MAGIC;
    result = (cap_t) (raw_data + 1);
    memset(result, 0, sizeof(*result));

    result->head.version = _LINUX_CAPABILITY_VERSION_1;

    return result;
}
Пример #12
0
int cap_free(void *data_p)
{

    if ( good_cap_t(data_p) ) {
        data_p = -1 + (__u32 *) data_p;
        memset(data_p, 0, sizeof(__u32) + sizeof(struct _cap_struct));
        free(data_p);
        data_p = NULL;
        return 0;
    }

    if ( good_cap_string(data_p) ) {
        int length = strlen(data_p) + sizeof(__u32);
        data_p = -1 + (__u32 *) data_p;
        memset(data_p, 0, length);
        free(data_p);
        data_p = NULL;
        return 0;
    }

    _cap_debug("don't recognize what we're supposed to liberate");
    errno = EINVAL;
    return -1;
}
Пример #13
0
static int _fcaps_save(struct vfs_cap_data *rawvfscap, cap_t cap_d,
		       int *bytes_p)
{
    __u32 eff_not_zero, magic;
    unsigned tocopy, i;

    if (!good_cap_t(cap_d)) {
	errno = EINVAL;
	return -1;
    }

    switch (cap_d->head.version) {
#ifdef _LINUX_CAPABILITY_VERSION_1
    case _LINUX_CAPABILITY_VERSION_1:
	magic = VFS_CAP_REVISION_1;
	tocopy = VFS_CAP_U32_1;
	*bytes_p = XATTR_CAPS_SZ_1;
	break;
#endif

#ifdef _LINUX_CAPABILITY_VERSION_2
    case _LINUX_CAPABILITY_VERSION_2:
	magic = VFS_CAP_REVISION_2;
	tocopy = VFS_CAP_U32_2;
	*bytes_p = XATTR_CAPS_SZ_2;
	break;
#endif

#ifdef _LINUX_CAPABILITY_VERSION_3
    case _LINUX_CAPABILITY_VERSION_3:
	magic = VFS_CAP_REVISION_2;
	tocopy = VFS_CAP_U32_2;
	*bytes_p = XATTR_CAPS_SZ_2;
	break;
#endif

    default:
	errno = EINVAL;
	return -1;
    }

    _cap_debug("setting named file capabilities");

    for (eff_not_zero = 0, i = 0; i < tocopy; i++) {
	eff_not_zero |= cap_d->u[i].flat[CAP_EFFECTIVE];
    }
    while (i < __CAP_BLKS) {
	if ((cap_d->u[i].flat[CAP_EFFECTIVE]
	     || cap_d->u[i].flat[CAP_INHERITABLE]
	     || cap_d->u[i].flat[CAP_PERMITTED])) {
	    /*
	     * System does not support these capabilities
	     */
	    errno = EINVAL;
	    return -1;
	}
	i++;
    }

    for (i=0; i < tocopy; i++) {
	rawvfscap->data[i].permitted
	    = FIXUP_32BITS(cap_d->u[i].flat[CAP_PERMITTED]);
	rawvfscap->data[i].inheritable
	    = FIXUP_32BITS(cap_d->u[i].flat[CAP_INHERITABLE]);

	if (eff_not_zero
	    && ((~(cap_d->u[i].flat[CAP_EFFECTIVE]))
		& (cap_d->u[i].flat[CAP_PERMITTED]
		   | cap_d->u[i].flat[CAP_INHERITABLE]))) {
	    errno = EINVAL;
	    return -1;
	}
    }

    if (eff_not_zero == 0) {
	rawvfscap->magic_etc = FIXUP_32BITS(magic);
    } else {
	rawvfscap->magic_etc = FIXUP_32BITS(magic|VFS_CAP_FLAGS_EFFECTIVE);
    }

    return 0;      /* success */
}
Пример #14
0
cap_t cap_from_text(const char *str)
{
    cap_t res;
    __cap_s allones;
    int n;

    if (str == NULL) {
	_cap_debug("bad argument");
	errno = EINVAL;
	return NULL;
    }

    if (!(res = cap_init()))
	return NULL;
    for (n = __CAP_BLKS; n--; )
	allones._blk[n] = -1;
    _cap_debug("%s", str);

    for (;;) {
	char op;
	int flags = 0, listed=0;
	__cap_s list = {{0}};

	/* skip leading spaces */
	while (isspace((unsigned char)*str))
	    str++;
	if (!*str) {
	    _cap_debugcap("e = ", &res->set.effective);
	    _cap_debugcap("i = ", &res->set.inheritable);
	    _cap_debugcap("p = ", &res->set.permitted);
	    return res;
	}

	/* identify caps specified by this clause */
	if (isalnum((unsigned char)*str) || *str == '_') {
	    for (;;) {
		if (namcmp(str, "all")) {
		    str += 3;
		    list = allones;
		} else {
		    n = lookupname(&str);
		    if (n == -1)
			goto bad;
		    list.raise_cap(n);
		}
		if (*str != ',')
		    break;
		if (!isalnum((unsigned char)*++str) && *str != '_')
		    goto bad;
	    }
	    listed = 1;
	} else if (*str == '+' || *str == '-')
	    goto bad;                    /* require a list of capabilities */
	else
	    list = allones;

	/* identify first operation on list of capabilities */
	op = *str++;
	if (op == '=' && (*str == '+' || *str == '-')) {
	    if (!listed)
		goto bad;
	    op = (*str++ == '+' ? 'P':'M'); /* skip '=' and take next op */
	} else if (op != '+' && op != '-' && op != '=')
	    goto bad;

	/* cycle through list of actions */
	do {
	    _cap_debug("next char = `%c'", *str);
	    if (*str && !isspace(*str)) {
		switch (*str++) {    /* Effective, Inheritable, Permitted */
		case 'e':
		    flags |= LIBCAP_EFF;
		    break;
		case 'i':
		    flags |= LIBCAP_INH;
		    break;
		case 'p':
		    flags |= LIBCAP_PER;
		    break;
		default:
		    goto bad;
		}
	    } else if (op != '=') {
		_cap_debug("only '=' can be followed by space");
		goto bad;
	    }

	    _cap_debug("how to read?");
	    switch (op) {               /* how do we interpret the caps? */
	    case '=':
	    case 'P':                                              /* =+ */
	    case 'M':                                              /* =- */
		clrbits(&res->set.effective,   &list);
		clrbits(&res->set.inheritable, &list);
		clrbits(&res->set.permitted,   &list);
		/* fall through */
		if (op == 'M')
		    goto minus;
	    case '+':
		if (flags & LIBCAP_EFF)
		    setbits(&res->set.effective,   &list);
		if (flags & LIBCAP_INH)
		    setbits(&res->set.inheritable, &list);
		if (flags & LIBCAP_PER)
		    setbits(&res->set.permitted,   &list);
		break;
	    case '-':
	    minus:
	        if (flags & LIBCAP_EFF)
		    clrbits(&res->set.effective,   &list);
		if (flags & LIBCAP_INH)
		    clrbits(&res->set.inheritable, &list);
		if (flags & LIBCAP_PER)
		    clrbits(&res->set.permitted,   &list);
		break;
	    }

	    /* new directive? */
	    if (*str == '+' || *str == '-') {
		if (!listed) {
		    _cap_debug("for + & - must list capabilities");
		    goto bad;
		}
		flags = 0;                       /* reset the flags */
		op = *str++;
		if (!isalpha(*str))
		    goto bad;
	    }
	} while (*str && !isspace(*str));
	_cap_debug("next clause");
    }

bad:
    cap_free(&res);
    errno = EINVAL;
    return NULL;
}
Пример #15
0
char *cap_to_text(cap_t caps, ssize_t *length_p)
{
    static char buf[CAP_TEXT_SIZE+CAP_TEXT_BUFFER_ZONE];
    char *p;
    int histo[8] = {0};
    int m, n, t;

    /* Check arguments */
    if (!good_cap_t(caps)) {
	errno = EINVAL;
	return NULL;
    }

    _cap_debugcap("e = ", &caps->set.effective);
    _cap_debugcap("i = ", &caps->set.inheritable);
    _cap_debugcap("p = ", &caps->set.permitted);

    for (n = __CAP_BITS; n--; )
	histo[getstateflags(caps, n)]++;

    for (m=t=7; t--; )
	if (histo[t] > histo[m])
	    m = t;

    /* blank is not a valid capability set */
    p = sprintf(buf, "=%s%s%s",
		(m & LIBCAP_EFF) ? "e" : "",
		(m & LIBCAP_INH) ? "i" : "",
		(m & LIBCAP_PER) ? "p" : "" ) + buf;

    for (t = 8; t--; )
	if (t != m && histo[t]) {
	    *p++ = ' ';
	    for (n = 0; n != __CAP_BITS; n++)
		if (getstateflags(caps, n) == t) {
		    if (_cap_names[n])
			p += sprintf(p, "%s,", _cap_names[n]);
		    else
			p += sprintf(p, "%d,", n);
		    if (p - buf > CAP_TEXT_SIZE) {
			errno = ERANGE;
			return NULL;
		    }
		}
	    p--;
	    n = t & ~m;
	    if (n)
		p += sprintf(p, "+%s%s%s",
			     (n & LIBCAP_EFF) ? "e" : "",
			     (n & LIBCAP_INH) ? "i" : "",
			     (n & LIBCAP_PER) ? "p" : "");
	    n = ~t & m;
	    if (n)
		p += sprintf(p, "-%s%s%s",
			     (n & LIBCAP_EFF) ? "e" : "",
			     (n & LIBCAP_INH) ? "i" : "",
			     (n & LIBCAP_PER) ? "p" : "");
	    if (p - buf > CAP_TEXT_SIZE) {
		errno = ERANGE;
		return NULL;
	    }
	}

    _cap_debug("%s", buf);
    if (length_p) {
	*length_p = p - buf;
    }

    return (_libcap_strdup(buf));
}