11d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich/* 21d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * filecap.c - A program that lists running processes with capabilities 31d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Copyright (c) 2009-10 Red Hat Inc., Durham, North Carolina. 41d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * All Rights Reserved. 51d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * 61d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * This software may be freely redistributed and/or modified under the 71d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * terms of the GNU General Public License as published by the Free 81d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Software Foundation; either version 2, or (at your option) any 91d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * later version. 101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * 111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * This program is distributed in the hope that it will be useful, 121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * but WITHOUT ANY WARRANTY; without even the implied warranty of 131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * GNU General Public License for more details. 151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * 161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * You should have received a copy of the GNU General Public License 171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * along with this program; see the file COPYING. If not, write to the 181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * 201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Authors: 211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Steve Grubb <sgrubb@redhat.com> 221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich */ 231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include "config.h" 251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <stdio.h> 261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <stdlib.h> 271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <string.h> 281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <errno.h> 291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include "cap-ng.h" 301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define __USE_GNU 1 311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <fcntl.h> 321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#define __USE_XOPEN_EXTENDED 1 331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <ftw.h> 341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic int show_all = 0, header = 0, capabilities = 0, cremove = 0; 361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic void usage(void) 381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{ 391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich fprintf(stderr, 401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich "usage: filecap [-a | -d | /dir | /dir/file [cap1 cap2 ...] ]\n"); 411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich exit(1); 421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich} 431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic int check_file(const char *fpath, 451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich const struct stat *sb, 461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich int typeflag_unused __attribute__ ((unused)), 471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich struct FTW *s_unused __attribute__ ((unused))) 481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{ 491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (S_ISREG(sb->st_mode) == 0) 501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich return FTW_CONTINUE; 511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich int fd = open(fpath, O_RDONLY|O_CLOEXEC); 531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (fd >= 0) { 541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capng_results_t rc; 551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capng_clear(CAPNG_SELECT_BOTH); 571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capng_get_caps_fd(fd); 581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich rc = capng_have_capabilities(CAPNG_SELECT_CAPS); 591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (rc > CAPNG_NONE) { 601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (header == 0) { 611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich header = 1; 621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("%-20s capabilities\n", "file"); 631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("%s ", fpath); 651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (rc == CAPNG_FULL) 661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("full"); 671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich else 681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capng_print_caps_text(CAPNG_PRINT_STDOUT, 691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich CAPNG_PERMITTED); 701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("\n"); 711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich close(fd); 731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich return FTW_CONTINUE; 751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich} 761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// Use cases: 791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// filecap 801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// filecap -a 811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// filecap /path/dir 821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// filecap /path/file 831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// filecap /path/file capability1 capability2 capability 3 ... 841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich// 851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichint main(int argc, char *argv[]) 861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{ 871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#if CAP_LAST_CAP < 31 || !defined (VFS_CAP_U32) || !defined (HAVE_ATTR_XATTR_H) 881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("File based capabilities are not supported\n"); 891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#else 901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich char *path_env, *path = NULL, *dir = NULL; 911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich struct stat sbuf; 921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich int nftw_flags = FTW_PHYS; 931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich int i; 941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (argc >1) { 961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich for (i=1; i<argc; i++) { 971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (strcmp(argv[i], "-a") == 0) { 981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich show_all = 1; 991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (argc != 2) 1001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich usage(); 1011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } else if (strcmp(argv[i], "-d") == 0) { 1021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich for (i=0; i<=CAP_LAST_CAP; i++) { 1031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich const char *n = 1041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capng_capability_to_name(i); 1051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (n == NULL) 1061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich n = "unknown"; 1071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("%s\n", n); 1081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich return 0; 1101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } else if (argv[i][0] == '/') { 1111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (lstat(argv[i], &sbuf) != 0) { 1121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("Error checking path %s (%s)\n", 1131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich argv[i], strerror(errno)); 1141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich exit(1); 1151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // Clear all capabilities in case cap strings 1171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // follow. If we get a second file we err out 1181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // so this is safe 1191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (S_ISREG(sbuf.st_mode) && path == NULL && 1201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich dir == NULL) { 1211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich path = argv[i]; 1221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capng_clear(CAPNG_SELECT_BOTH); 1231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } else if (S_ISDIR(sbuf.st_mode) && path == NULL 1241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich && dir == NULL) 1251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich dir = argv[i]; 1261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich else { 1271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("Must be one regular file or " 1281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich "directory\n"); 1291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich exit(1); 1301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } else { 1321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich int cap = capng_name_to_capability(argv[i]); 1331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (cap >= 0) { 1341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (path == NULL) 1351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich usage(); 1361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capng_update(CAPNG_ADD, 1371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich CAPNG_PERMITTED|CAPNG_EFFECTIVE, 1381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich cap); 1391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capabilities = 1; 1401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } else if (strcmp("none", argv[i]) == 0) { 1411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capng_clear(CAPNG_SELECT_BOTH); 1421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capabilities = 1; 1431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich cremove = 1; 1441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } else { 1451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("Unrecognized capability.\n"); 1461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich usage(); 1471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (path == NULL && dir == NULL && show_all == 0) { 1521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich path_env = getenv("PATH"); 1531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (path_env != NULL) { 1541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich path = strdup(path_env); 1551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich for (dir=strtok(path,":"); dir!=NULL; 1561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich dir=strtok(NULL,":")) { 1571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich nftw(dir, check_file, 1024, nftw_flags); 1581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich free(path); 1601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } else if (path == NULL && dir == NULL && show_all == 1) { 1621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // Find files 1631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich nftw("/", check_file, 1024, nftw_flags); 1641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } else if (dir) { 1651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // Print out the dir 1661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich nftw(dir, check_file, 1024, nftw_flags); 1671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich }else if (path && capabilities == 0) { 1681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // Print out specific file 1691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich check_file(path, &sbuf, 0, NULL); 1701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } else if (path && capabilities == 1) { 1711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // Write capabilities to file 1721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich int fd = open(path, O_WRONLY|O_NOFOLLOW|O_CLOEXEC); 1731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (fd < 0) { 1741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("Could not open %s for writing (%s)\n", path, 1751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich strerror(errno)); 1761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich return 1; 1771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capng_apply_caps_fd(fd); 1791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich close(fd); 1801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#endif 1821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich return 0; 1831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich} 1841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 185