11d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich/* libcap-ng.c --
21d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Copyright 2009-10 Red Hat Inc., Durham, North Carolina.
31d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * All Rights Reserved.
41d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *
51d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * This library is free software; you can redistribute it and/or
61d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * modify it under the terms of the GNU Lesser General Public
71d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * License as published by the Free Software Foundation; either
81d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * version 2.1 of the License, or (at your option) any later version.
91d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *
101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * This library is distributed in the hope that it will be useful,
111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * but WITHOUT ANY WARRANTY; without even the implied warranty of
121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Lesser General Public License for more details.
141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *
151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * You should have received a copy of the GNU Lesser General Public
161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * License along with this library; if not, write to the Free Software
171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *
191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Authors:
201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *      Steve Grubb <sgrubb@redhat.com>
211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich */
221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include "config.h"
241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include "cap-ng.h"
251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <string.h>
261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <stdarg.h>
271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <stdio.h>
281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#if !defined(ANDROID)
291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <stdio_ext.h>
301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <stdlib.h>
321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <sys/prctl.h>
331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <grp.h>
341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <sys/stat.h>
351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <stdarg.h>
361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <errno.h>
371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <byteswap.h>
381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef HAVE_SYSCALL_H
391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <sys/syscall.h>
401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef HAVE_LINUX_SECUREBITS_H
421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <linux/securebits.h>
431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich/*
461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Some milestones of when things became available:
471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * 2.6.24 kernel	XATTR_NAME_CAPS
481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * 2.6.25 kernel	PR_CAPBSET_DROP, CAPABILITY_VERSION_2
491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * 2.6.26 kernel	PR_SET_SECUREBITS, SECURE_*_LOCKED, VERSION_3
501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich */
511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich/* External syscall prototypes */
531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichextern int capset(cap_user_header_t header, cap_user_data_t data);
541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichextern int capget(cap_user_header_t header, const cap_user_data_t data);
551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// Local defines
571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define MASK(x) (1U << (x))
581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_CAPBSET_DROP
591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define UPPER_MASK ~(unsigned)((~0U)<<(CAP_LAST_CAP-31))
601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#else
611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// For v1 systems UPPER_MASK will never be used
621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define UPPER_MASK (unsigned)(~0U)
631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// Re-define cap_valid so its uniform between V1 and V3
661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#undef cap_valid
671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define cap_valid(x) ((x) <= CAP_LAST_CAP)
681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// If we don't have the xattr library, then we can't
701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// compile-in file system capabilities
711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef HAVE_ATTR_XATTR_H
721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#undef VFS_CAP_U32
731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef VFS_CAP_U32
761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich #include <attr/xattr.h>
771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich #if __BYTE_ORDER == __BIG_ENDIAN
781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich  #define FIXUP(x) bswap_32(x)
791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich #else
801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich  #define FIXUP(x) (x)
811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich #endif
821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef _LINUX_CAPABILITY_VERSION_1
851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define _LINUX_CAPABILITY_VERSION_1 0x19980330
861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef _LINUX_CAPABILITY_VERSION_2
881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define _LINUX_CAPABILITY_VERSION_2 0x20071026
891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef _LINUX_CAPABILITY_VERSION_3
911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define _LINUX_CAPABILITY_VERSION_3 0x20080522
921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// This public API went private in the 2.6.36 kernel - hope it never changes
951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef XATTR_CAPS_SUFFIX
961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define XATTR_CAPS_SUFFIX "capability"
971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef XATTR_SECURITY_PREFIX
991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define XATTR_SECURITY_PREFIX "security."
1001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
1011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef XATTR_NAME_CAPS
1021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
1031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
1041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich/* Child processes can't get caps back */
1071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef SECURE_NOROOT
1081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define SECURE_NOROOT                   0
1091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
1101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef SECURE_NOROOT_LOCKED
1111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define SECURE_NOROOT_LOCKED            1  /* make bit-0 immutable */
1121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
1131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich/* Setuid apps run by uid 0 don't get caps back */
1141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef SECURE_NO_SETUID_FIXUP
1151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define SECURE_NO_SETUID_FIXUP          2
1161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
1171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef SECURE_NO_SETUID_FIXUP_LOCKED
1181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define SECURE_NO_SETUID_FIXUP_LOCKED   3  /* make bit-2 immutable */
1191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
1201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// States: new, allocated, initted, updated, applied
1221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichtypedef enum { CAPNG_NEW, CAPNG_ERROR, CAPNG_ALLOCATED, CAPNG_INIT,
1231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	CAPNG_UPDATED, CAPNG_APPLIED } capng_states_t;
1241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// Create an easy data struct out of the kernel definitions
1261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichtypedef union {
1271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	struct __user_cap_data_struct v1;
1281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	struct __user_cap_data_struct v3[2];
1291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich} cap_data_t;
1301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// This struct keeps all state info
1321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstruct cap_ng
1331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
1341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	int cap_ver;
1351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	struct __user_cap_header_struct hdr;
1361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	cap_data_t data;
1371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	capng_states_t state;
1381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	__u32 bounds[2];
1391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich};
1401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// Global variables with per thread uniqueness
1421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic __thread struct cap_ng m =	{ 1,
1431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					{0, 0},
1441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					{ {0, 0, 0} },
1451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					CAPNG_NEW,
1461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					{0, 0} };
1471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic void init(void)
1501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
1511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state != CAPNG_NEW)
1521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return;
1531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	memset(&m.hdr, 0, sizeof(m.hdr));
1551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	(void)capget(&m.hdr, NULL); // Returns -EINVAL
1561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.hdr.version == _LINUX_CAPABILITY_VERSION_3 ||
1571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.hdr.version == _LINUX_CAPABILITY_VERSION_2) {
1581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.cap_ver = 3;
1591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	} else if (m.hdr.version == _LINUX_CAPABILITY_VERSION_1) {
1601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.cap_ver = 1;
1611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	} else {
1621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.state = CAPNG_ERROR;
1631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return;
1641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
1651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	memset(&m.data, 0, sizeof(cap_data_t));
1671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef HAVE_SYSCALL_H
1681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	m.hdr.pid = (unsigned)syscall(__NR_gettid);
1691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#else
1701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	m.hdr.pid = (unsigned)getpid();
1711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
1721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	m.state = CAPNG_ALLOCATED;
1731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
1741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichvoid capng_clear(capng_select_t set)
1761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
1771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state == CAPNG_NEW)
1781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		init();
1791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state == CAPNG_ERROR)
1801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return;
1811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (set & CAPNG_SELECT_CAPS)
1831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		memset(&m.data, 0, sizeof(cap_data_t));
1841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_CAPBSET_DROP
1851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (set & CAPNG_SELECT_BOUNDS)
1861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		memset(m.bounds, 0, sizeof(m.bounds));
1871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
1881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	m.state = CAPNG_INIT;
1891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
1901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichvoid capng_fill(capng_select_t set)
1921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
1931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state == CAPNG_NEW)
1941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		init();
1951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state == CAPNG_ERROR)
1961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return;
1971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
1981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (set & CAPNG_SELECT_CAPS) {
1991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (m.cap_ver == 1) {
2001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.data.v1.effective = 0x7FFFFFFFU;
2011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.data.v1.permitted = 0x7FFFFFFFU;
2021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.data.v1.inheritable = 0;
2031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		} else {
2041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.data.v3[0].effective = 0xFFFFFFFFU;
2051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.data.v3[0].permitted = 0xFFFFFFFFU;
2061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.data.v3[0].inheritable = 0;
2071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.data.v3[1].effective = 0xFFFFFFFFU;
2081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.data.v3[1].permitted = 0xFFFFFFFFU;
2091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.data.v3[1].inheritable = 0;
2101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		}
2111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
2121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_CAPBSET_DROP
2131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (set & CAPNG_SELECT_BOUNDS) {
2141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		unsigned i;
2151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		for (i=0; i<sizeof(m.bounds)/sizeof(__u32); i++)
2161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.bounds[i] = 0xFFFFFFFFU;
2171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
2181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
2191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	m.state = CAPNG_INIT;
2201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
2211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichvoid capng_setpid(int pid)
2231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
2241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state == CAPNG_NEW)
2251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		init();
2261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state == CAPNG_ERROR)
2271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return;
2281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	m.hdr.pid = pid;
2301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
2311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_CAPBSET_DROP
2331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic int get_bounding_set(void)
2341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
2351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	char buf[64];
2361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	FILE *f;
2371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	snprintf(buf, sizeof(buf), "/proc/%u/status", m.hdr.pid ? m.hdr.pid :
2391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef HAVE_SYSCALL_H
2401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		(unsigned)syscall(__NR_gettid));
2411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#else
2421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		(unsigned)getpid();
2431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
2441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	f = fopen(buf, "re");
2451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (f == NULL)
2461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -1;
2471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#if !defined(ANDROID)
2481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	__fsetlocking(f, FSETLOCKING_BYCALLER);
2491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
2501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	while (fgets(buf, sizeof(buf), f)) {
2511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (strncmp(buf, "CapB", 4))
2521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			continue;
2531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		sscanf(buf, "CapBnd:  %08x%08x", &m.bounds[1], &m.bounds[0]);
2541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		fclose(f);
2551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return 0;
2561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
2571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	fclose(f);
2581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return -1;
2591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
2601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
2611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichint capng_get_caps_process(void)
2631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
2641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	int rc;
2651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state == CAPNG_NEW)
2671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		init();
2681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state == CAPNG_ERROR)
2691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -1;
2701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	rc = capget((cap_user_header_t)&m.hdr, (cap_user_data_t)&m.data);
2721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (rc == 0) {
2731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.state = CAPNG_INIT;
2741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_CAPBSET_DROP
2751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		rc = get_bounding_set();
2761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (rc < 0)
2771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.state = CAPNG_ERROR;
2781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
2791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
2801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return rc;
2821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
2831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef VFS_CAP_U32
2851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic int load_data(const struct vfs_cap_data *filedata, int size)
2861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
2871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	unsigned int magic;
2881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.cap_ver == 1)
2901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -1;	// Should never get here but just in case
2911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
2921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	magic = FIXUP(filedata->magic_etc);
2931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	switch (magic & VFS_CAP_REVISION_MASK)
2941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	{
2951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		case VFS_CAP_REVISION_1:
2961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.cap_ver = 1;
2971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (size != XATTR_CAPS_SZ_1)
2981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				return -1;
2991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			break;
3001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		case VFS_CAP_REVISION_2:
3011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.cap_ver = 2;
3021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (size != XATTR_CAPS_SZ_2)
3031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				return -1;
3041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			break;
3051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		default:
3061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return -1;
3071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
3081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
3091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Now stuff the data structures
3101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	m.data.v3[0].permitted = FIXUP(filedata->data[0].permitted);
3111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	m.data.v3[1].permitted = FIXUP(filedata->data[1].permitted);
3121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	m.data.v3[0].inheritable = FIXUP(filedata->data[0].inheritable);
3131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	m.data.v3[1].inheritable = FIXUP(filedata->data[1].inheritable);
3141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (magic & VFS_CAP_FLAGS_EFFECTIVE) {
3151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.data.v3[0].effective =
3161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.data.v3[0].permitted | m.data.v3[0].inheritable;
3171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.data.v3[1].effective =
3181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.data.v3[1].permitted | m.data.v3[1].inheritable;
3191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	} else {
3201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.data.v3[0].effective = 0;
3211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.data.v3[1].effective = 0;
3221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
3231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return 0;
3241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
3251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
3261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
3271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichint capng_get_caps_fd(int fd)
3281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
3291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef VFS_CAP_U32
3301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return -1;
3311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#else
3321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	int rc;
3331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	struct vfs_cap_data filedata;
3341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
3351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state == CAPNG_NEW)
3361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		init();
3371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state == CAPNG_ERROR)
3381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -1;
3391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
3401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	rc = fgetxattr(fd, XATTR_NAME_CAPS, &filedata, sizeof(filedata));
3411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (rc <= 0)
3421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -1;
3431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
3441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	rc = load_data(&filedata, rc);
3451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (rc == 0)
3461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.state = CAPNG_INIT;
3471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
3481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return rc;
3491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
3501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
3511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
3521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic void v1_update(capng_act_t action, unsigned int capability, __u32 *data)
3531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
3541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (action == CAPNG_ADD)
3551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		*data |= MASK(capability);
3561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	else
3571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		*data &= ~(MASK(capability));
3581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
3591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
3601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic void update_effective(capng_act_t action, unsigned int capability,
3611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	unsigned int idx)
3621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
3631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (action == CAPNG_ADD)
3641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.data.v3[idx].effective |= MASK(capability);
3651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	else
3661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.data.v3[idx].effective &= ~(MASK(capability));
3671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
3681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
3691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic void update_permitted(capng_act_t action, unsigned int capability,
3701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	unsigned int idx)
3711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
3721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (action == CAPNG_ADD)
3731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.data.v3[idx].permitted |= MASK(capability);
3741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	else
3751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.data.v3[idx].permitted &= ~(MASK(capability));
3761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
3771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
3781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic void update_inheritable(capng_act_t action, unsigned int capability,
3791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	unsigned int idx)
3801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
3811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (action == CAPNG_ADD)
3821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.data.v3[idx].inheritable |= MASK(capability);
3831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	else
3841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.data.v3[idx].inheritable &= ~(MASK(capability));
3851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
3861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
3871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic void update_bounding_set(capng_act_t action, unsigned int capability,
3881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	unsigned int idx)
3891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
3901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_CAPBSET_DROP
3911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (action == CAPNG_ADD)
3921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.bounds[idx] |= MASK(capability);
3931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	else
3941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.bounds[idx] &= ~(MASK(capability));
3951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
3961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
3971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
3981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichint capng_update(capng_act_t action, capng_type_t type, unsigned int capability)
3991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
4001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Before updating, we expect that the data is initialized to something
4011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state < CAPNG_INIT)
4021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -1;
4031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (!cap_valid(capability)) {
4041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		errno = EINVAL;
4051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -1;
4061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
4071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
4081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.cap_ver == 1) {
4091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (CAPNG_EFFECTIVE & type)
4101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			v1_update(action, capability, &m.data.v1.effective);
4111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (CAPNG_PERMITTED & type)
4121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			v1_update(action, capability, &m.data.v1.permitted);
4131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (CAPNG_INHERITABLE & type)
4141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			v1_update(action, capability, &m.data.v1.inheritable);
4151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	} else {
4161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		int idx;
4171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
4181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (capability > 31) {
4191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			idx = capability>>5;
4201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capability %= 32;
4211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		} else
4221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			idx = 0;
4231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
4241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (CAPNG_EFFECTIVE & type)
4251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			update_effective(action, capability, idx);
4261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (CAPNG_PERMITTED & type)
4271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			update_permitted(action, capability, idx);
4281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (CAPNG_INHERITABLE & type)
4291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			update_inheritable(action, capability, idx);
4301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (CAPNG_BOUNDING_SET & type)
4311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			update_bounding_set(action, capability, idx);
4321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
4331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
4341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	m.state = CAPNG_UPDATED;
4351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return 0;
4361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
4371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
4381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichint capng_updatev(capng_act_t action, capng_type_t type,
4391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich                unsigned int capability, ...)
4401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
4411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	int rc;
4421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	unsigned int cap;
4431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	va_list ap;
4441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
4451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	rc = capng_update(action, type, capability);
4461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (rc)
4471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return rc;
4481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	va_start(ap, capability);
4491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	cap = va_arg(ap, unsigned int);
4501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	while (cap_valid(cap)) {
4511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		rc = capng_update(action, type, cap);
4521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (rc)
4531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			break;
4541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		cap = va_arg(ap, unsigned int);
4551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
4561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	va_end(ap);
4571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
4581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// See if planned exit or invalid
4591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (cap == (unsigned)-1)
4601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		rc = 0;
4611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	else {
4621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		rc = -1;
4631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		errno = EINVAL;
4641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
4651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
4661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return rc;
4671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
4681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
4691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichint capng_apply(capng_select_t set)
4701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
4711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	int rc = -1;
4721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
4731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Before updating, we expect that the data is initialized to something
4741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state < CAPNG_INIT)
4751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -1;
4761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
4771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (set & CAPNG_SELECT_BOUNDS) {
4781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_CAPBSET_DROP
4791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		void *s = capng_save_state();
4801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		capng_get_caps_process();
4811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
4821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			int i;
4831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capng_restore_state(&s);
4841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			rc = 0;
4851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			for (i=0; i <= CAP_LAST_CAP && rc == 0; i++)
4861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				if (capng_have_capability(CAPNG_BOUNDING_SET,
4871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich								 i) == 0)
4881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					rc = prctl(PR_CAPBSET_DROP, i, 0, 0, 0);
4891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (rc == 0)
4901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				m.state = CAPNG_APPLIED;
4911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		} else
4921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capng_restore_state(&s);
4931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#else
4941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		rc = 0;
4951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
4961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
4971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (set & CAPNG_SELECT_CAPS) {
4981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		rc = capset((cap_user_header_t)&m.hdr,
4991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				(cap_user_data_t)&m.data);
5001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (rc == 0)
5011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			m.state = CAPNG_APPLIED;
5021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
5031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return rc;
5041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
5051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
5061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef VFS_CAP_U32
5071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic int save_data(struct vfs_cap_data *filedata, int *size)
5081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
5091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Now stuff the data structures
5101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.cap_ver == 1) {
5111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		filedata->data[0].permitted = FIXUP(m.data.v1.permitted);
5121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		filedata->data[0].inheritable = FIXUP(m.data.v1.inheritable);
5131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		filedata->magic_etc = FIXUP(VFS_CAP_REVISION_1);
5141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		*size = XATTR_CAPS_SZ_1;
5151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	} else {
5161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		int eff;
5171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
5181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (m.data.v3[0].effective || m.data.v3[1].effective)
5191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			eff = VFS_CAP_FLAGS_EFFECTIVE;
5201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else
5211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			eff = 0;
5221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		filedata->data[0].permitted = FIXUP(m.data.v3[0].permitted);
5231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		filedata->data[0].inheritable = FIXUP(m.data.v3[0].inheritable);
5241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		filedata->data[1].permitted = FIXUP(m.data.v3[1].permitted);
5251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		filedata->data[1].inheritable = FIXUP(m.data.v3[1].inheritable);
5261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		filedata->magic_etc = FIXUP(VFS_CAP_REVISION_2 | eff);
5271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		*size = XATTR_CAPS_SZ_2;
5281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
5291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
5301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return 0;
5311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
5321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
5331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
5341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichint capng_apply_caps_fd(int fd)
5351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
5361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifndef VFS_CAP_U32
5371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return -1;
5381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#else
5391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	int rc, size;
5401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	struct vfs_cap_data filedata;
5411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	struct stat buf;
5421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
5431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Before updating, we expect that the data is initialized to something
5441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state < CAPNG_INIT)
5451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -1;
5461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
5471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (fstat(fd, &buf) != 0)
5481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -1;
5491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (S_ISLNK(buf.st_mode) || !S_ISREG(buf.st_mode)) {
5501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		errno = EINVAL;
5511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -1;
5521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
5531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (capng_have_capabilities(CAPNG_SELECT_CAPS) == CAPNG_NONE)
5541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		rc = fremovexattr(fd, XATTR_NAME_CAPS);
5551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	else {
5561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		save_data(&filedata, &size);
5571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		rc = fsetxattr(fd, XATTR_NAME_CAPS, &filedata, size, 0);
5581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
5591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
5601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (rc == 0)
5611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		m.state = CAPNG_APPLIED;
5621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
5631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return rc;
5641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
5651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
5661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
5671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// Change uids keeping/removing only certain capabilities
5681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// flag to drop supp groups
5691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichint capng_change_id(int uid, int gid, capng_flags_t flag)
5701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
5711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	int rc, need_setgid, need_setuid;
5721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
5731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Before updating, we expect that the data is initialized to something
5741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state < CAPNG_INIT)
5751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -1;
5761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
5771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Check the current capabilities
5781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_CAPBSET_DROP
5791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// If newer kernel, we need setpcap to change the bounding set
5801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP) == 0 &&
5811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					flag & CAPNG_CLEAR_BOUNDING)
5821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		capng_update(CAPNG_ADD,
5831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_SETPCAP);
5841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
5851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (gid == -1 || capng_have_capability(CAPNG_EFFECTIVE, CAP_SETGID))
5861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		need_setgid = 0;
5871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	else {
5881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		need_setgid = 1;
5891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
5901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				CAP_SETGID);
5911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
5921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (uid == -1 || capng_have_capability(CAPNG_EFFECTIVE, CAP_SETUID))
5931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		need_setuid = 0;
5941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	else {
5951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		need_setuid = 1;
5961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
5971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				CAP_SETUID);
5981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
5991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Tell system we want to keep caps across uid change
6011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0))
6021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -2;
6031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Change to the temp capabilities
6051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	rc = capng_apply(CAPNG_SELECT_CAPS);
6061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (rc < 0)
6071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -3;
6081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Clear bounding set if needed while we have CAP_SETPCAP
6101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (flag & CAPNG_CLEAR_BOUNDING) {
6111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		capng_clear(CAPNG_BOUNDING_SET);
6121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		rc = capng_apply(CAPNG_SELECT_BOUNDS);
6131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (rc)
6141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return -8;
6151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
6161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Change gid
6181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (gid != -1) {
6191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		rc = setresgid(gid, gid, gid);
6201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (rc)
6211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return -4;
6221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
6231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// See if we need to unload supplemental groups
6251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if ((flag & CAPNG_DROP_SUPP_GRP) && gid != -1) {
6261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (setgroups(0, NULL))
6271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return -5;
6281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
6291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Change uid
6311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (uid != -1) {
6321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		rc = setresuid(uid, uid, uid);
6331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (rc)
6341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return -6;
6351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
6361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Tell it we are done keeping capabilities
6381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	rc = prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0);
6391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (rc)
6401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -7;
6411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Now throw away CAP_SETPCAP so no more changes
6431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (need_setgid)
6441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
6451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				CAP_SETGID);
6461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (need_setuid)
6471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
6481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				CAP_SETUID);
6491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Now drop setpcap & apply
6511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	capng_update(CAPNG_DROP, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
6521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				CAP_SETPCAP);
6531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	rc = capng_apply(CAPNG_SELECT_CAPS);
6541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (rc < 0)
6551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -9;
6561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// Done
6581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	m.state = CAPNG_UPDATED;
6591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return 0;
6601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
6611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichint capng_lock(void)
6631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
6641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_SET_SECUREBITS
6651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	int rc = prctl(PR_SET_SECUREBITS,
6661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			1 << SECURE_NOROOT |
6671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			1 << SECURE_NOROOT_LOCKED |
6681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			1 << SECURE_NO_SETUID_FIXUP |
6691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			1 << SECURE_NO_SETUID_FIXUP_LOCKED, 0, 0, 0);
6701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (rc)
6711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return -1;
6721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
6731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return 0;
6751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
6761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// -1 - error, 0 - no caps, 1 partial caps, 2 full caps
6781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichcapng_results_t capng_have_capabilities(capng_select_t set)
6791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
6801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	int empty = 0, full = 0;
6811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// First, try to init with current set
6831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state < CAPNG_INIT)
6841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		capng_get_caps_process();
6851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// If we still don't have anything, error out
6871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state < CAPNG_INIT)
6881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return CAPNG_FAIL;
6891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
6901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (set & CAPNG_SELECT_CAPS) {
6911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (m.cap_ver == 1) {
6921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (m.data.v1.effective == 0)
6931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				empty = 1;
6941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			// after fill, 30 bits starts from upper to lower
6951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			else if (m.data.v1.effective == 0x7FFFFFFFU)
6961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				full = 1;
6971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			// actual capabilities read from system
6981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			else if (m.data.v1.effective == 0xFFFFFEFFU)
6991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				full = 1;
7001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			else
7011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				return CAPNG_PARTIAL;
7021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		} else {
7031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (m.data.v3[0].effective == 0)
7041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				empty = 1;
7051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			else if (m.data.v3[0].effective == 0xFFFFFFFFU)
7061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				full = 1;
7071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			else
7081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				return CAPNG_PARTIAL;
7091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if ((m.data.v3[1].effective & UPPER_MASK) == 0)
7101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				empty = 1;
7111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			else if ((m.data.v3[1].effective & UPPER_MASK) ==
7121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich							UPPER_MASK)
7131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				full = 1;
7141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			else
7151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				return CAPNG_PARTIAL;
7161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		}
7171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
7181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_CAPBSET_DROP
7191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (set & CAPNG_SELECT_BOUNDS) {
7201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (m.bounds[0] == 0)
7211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			empty = 1;
7221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else if (m.bounds[0] == 0xFFFFFFFFU)
7231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			full = 1;
7241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else
7251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return CAPNG_PARTIAL;
7261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if ((m.bounds[1] & UPPER_MASK) == 0)
7271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			empty = 1;
7281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else if ((m.bounds[1] & UPPER_MASK) == UPPER_MASK)
7291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			full = 1;
7301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else
7311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return CAPNG_PARTIAL;
7321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
7331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
7341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
7351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (empty == 1 && full == 0)
7361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return CAPNG_NONE;
7371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	else if (empty == 0 && full == 1)
7381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return CAPNG_FULL;
7391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
7401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return CAPNG_PARTIAL;
7411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
7421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
7431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic int check_effective(unsigned int capability, unsigned int idx)
7441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
7451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return MASK(capability) & m.data.v3[idx].effective ? 1 : 0;
7461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
7471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
7481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic int check_permitted(unsigned int capability, unsigned int idx)
7491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
7501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return MASK(capability) & m.data.v3[idx].permitted ? 1 : 0;
7511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
7521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
7531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic int check_inheritable(unsigned int capability, unsigned int idx)
7541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
7551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return MASK(capability) & m.data.v3[idx].inheritable ? 1 : 0;
7561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
7571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
7581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic int bounds_bit_check(unsigned int capability, unsigned int idx)
7591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
7601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_CAPBSET_DROP
7611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return MASK(capability) & m.bounds[idx] ? 1 : 0;
7621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#else
7631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return 0;
7641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
7651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
7661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
7671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic int v1_check(unsigned int capability, __u32 data)
7681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
7691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return MASK(capability) & data ? 1 : 0;
7701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
7711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
7721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichint capng_have_capability(capng_type_t which, unsigned int capability)
7731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
7741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// First, try to init with current set
7751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state < CAPNG_INIT)
7761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		capng_get_caps_process();
7771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
7781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	// If we still don't have anything, error out
7791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state < CAPNG_INIT)
7801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return CAPNG_FAIL;
7811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.cap_ver == 1 && capability > 31)
7821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return 0;
7831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (!cap_valid(capability))
7841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return 0;
7851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
7861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.cap_ver == 1) {
7871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (which == CAPNG_EFFECTIVE)
7881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return v1_check(capability, m.data.v1.effective);
7891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else if (which == CAPNG_PERMITTED)
7901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return v1_check(capability, m.data.v1.permitted);
7911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else if (which == CAPNG_INHERITABLE)
7921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return v1_check(capability, m.data.v1.inheritable);
7931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	} else {
7941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		unsigned int idx;
7951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
7961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (capability > 31) {
7971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			idx = capability>>5;
7981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			capability %= 32;
7991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		} else
8001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			idx = 0;
8011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
8021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (which == CAPNG_EFFECTIVE)
8031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return check_effective(capability, idx);
8041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else if (which == CAPNG_PERMITTED)
8051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return check_permitted(capability, idx);
8061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else if (which == CAPNG_INHERITABLE)
8071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return check_inheritable(capability, idx);
8081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else if (which == CAPNG_BOUNDING_SET)
8091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			return bounds_bit_check(capability, idx);
8101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
8111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return 0;
8121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
8131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
8141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichchar *capng_print_caps_numeric(capng_print_t where, capng_select_t set)
8151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
8161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	char *ptr = NULL;
8171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
8181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state < CAPNG_INIT)
8191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return ptr;
8201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
8211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (where == CAPNG_PRINT_STDOUT) {
8221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (set & CAPNG_SELECT_CAPS) {
8231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (m.cap_ver == 1) {
8241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf( "Effective:    %08X\n"
8251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					"Permitted:    %08X\n"
8261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					"Inheritable:  %08X\n",
8271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v1.effective,
8281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v1.permitted,
8291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v1.inheritable);
8301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			} else {
8311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				printf( "Effective:    %08X, %08X\n"
8321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					"Permitted:    %08X, %08X\n"
8331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					"Inheritable:  %08X, %08X\n",
8341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v3[1].effective & UPPER_MASK,
8351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v3[0].effective,
8361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v3[1].permitted & UPPER_MASK,
8371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v3[0].permitted,
8381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v3[1].inheritable & UPPER_MASK,
8391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v3[0].inheritable);
8401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
8411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			}
8421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		}
8431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_CAPBSET_DROP
8441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (set & CAPNG_SELECT_BOUNDS)
8451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("Bounding Set: %08X, %08X\n",
8461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				m.bounds[1] & UPPER_MASK, m.bounds[0]);
8471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
8481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	} else if (where == CAPNG_PRINT_BUFFER) {
8491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (set & CAPNG_SELECT_CAPS) {
8501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			// Make it big enough for bounding set, too
8511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			ptr = malloc(160);
8521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (m.cap_ver == 1) {
8531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				snprintf(ptr, 160,
8541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					"Effective:   %08X\n"
8551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					"Permitted:   %08X\n"
8561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					"Inheritable: %08X\n",
8571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v1.effective,
8581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v1.permitted,
8591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v1.inheritable);
8601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			} else {
8611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				snprintf(ptr, 160,
8621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					"Effective:   %08X, %08X\n"
8631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					"Permitted:   %08X, %08X\n"
8641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					"Inheritable: %08X, %08X\n",
8651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v3[1].effective & UPPER_MASK,
8661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v3[0].effective,
8671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v3[1].permitted & UPPER_MASK,
8681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v3[0].permitted,
8691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v3[1].inheritable & UPPER_MASK,
8701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.data.v3[0].inheritable);
8711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			}
8721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		}
8731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (set & CAPNG_SELECT_BOUNDS) {
8741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#ifdef PR_CAPBSET_DROP
8751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			char *s;
8761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (ptr == NULL ){
8771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				ptr = malloc(40);
8781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				if (ptr == NULL)
8791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					return ptr;
8801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				*ptr = 0;
8811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				s = ptr;
8821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			} else
8831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				s = ptr + strlen(ptr);
8841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			snprintf(s, 40, "Bounding Set: %08X, %08X\n",
8851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					m.bounds[1] & UPPER_MASK, m.bounds[0]);
8861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif
8871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		}
8881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
8891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
8901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return ptr;
8911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
8921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
8931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichchar *capng_print_caps_text(capng_print_t where, capng_type_t which)
8941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
8951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	unsigned int i;
8961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	int once = 0, cnt = 0;
8971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	char *ptr = NULL;
8981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
8991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (m.state < CAPNG_INIT)
9001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		return ptr;
9011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
9021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	for (i=0; i<=CAP_LAST_CAP; i++) {
9031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (capng_have_capability(which, i)) {
9041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			const char *n = capng_capability_to_name(i);
9051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (n == NULL)
9061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				n = "unknown";
9071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			if (where == CAPNG_PRINT_STDOUT) {
9081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				if (once == 0) {
9091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					printf("%s", n);
9101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					once++;
9111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				} else
9121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					printf(", %s", n);
9131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			} else if (where == CAPNG_PRINT_BUFFER) {
9141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				int len;
9151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				if (once == 0) {
9161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					ptr = malloc(CAP_LAST_CAP*18);
9171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					if (ptr == NULL)
9181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich						return ptr;
9191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					len = sprintf(ptr+cnt, "%s", n);
9201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					once++;
9211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				} else
9221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					len = sprintf(ptr+cnt, ", %s", n);
9231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich				if (len > 0)
9241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich					cnt+=len;
9251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			}
9261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		}
9271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
9281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (once == 0) {
9291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (where == CAPNG_PRINT_STDOUT)
9301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			printf("none");
9311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		else
9321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			ptr = strdup("none");
9331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
9341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return ptr;
9351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
9361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
9371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichvoid *capng_save_state(void)
9381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
9391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	void *ptr = malloc(sizeof(m));
9401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (ptr)
9411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		memcpy(ptr, &m, sizeof(m));
9421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	return ptr;
9431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
9441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
9451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichvoid capng_restore_state(void **state)
9461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{
9471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	if (state) {
9481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		void *ptr = *state;
9491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		if (ptr)
9501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich			memcpy(&m, ptr, sizeof(m));
9511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		free(ptr);
9521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich		*state = NULL;
9531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich	}
9541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich}
9551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich
956