11d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich/* 21d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * pscap.c - A program that lists running processes with capabilities 31d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich * Copyright (c) 2009,2012 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 <stdio_ext.h> 271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <unistd.h> 281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <stdlib.h> 291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <errno.h> 301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <string.h> 311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <dirent.h> 321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <fcntl.h> 331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include <pwd.h> 341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich#include "cap-ng.h" 351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichstatic void usage(void) 381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{ 391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich fprintf(stderr, "usage: pscap [-a]\n"); 401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich exit(1); 411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich} 421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevichint main(int argc, char *argv[]) 441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich{ 451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich DIR *d; 461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich struct dirent *ent; 471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich int header = 0, show_all = 0, caps; 481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich pid_t our_pid = getpid(); 491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (argc > 2) { 511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich fputs("Too many arguments\n", stderr); 521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich usage(); 531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (argc == 2) { 551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (strcmp(argv[1], "-a") == 0) 561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich show_all = 1; 571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich else 581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich usage(); 591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich d = opendir("/proc"); 621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (d == NULL) { 631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("Can't open /proc: %s\n", strerror(errno)); 641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich return 1; 651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich while (( ent = readdir(d) )) { 671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich int pid, ppid, uid = -1, euid = -1; 681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich char buf[100]; 691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich char *tmp, cmd[16], state, *name = NULL; 701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich int fd, len; 711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich struct passwd *p; 721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // Skip non-process dir entries 741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if(*ent->d_name<'0' || *ent->d_name>'9') 751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich continue; 761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich errno = 0; 771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich pid = strtol(ent->d_name, NULL, 10); 781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (errno) 791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich continue; 801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich /* Skip our pid so we aren't listed */ 821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (pid == our_pid) 831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich continue; 841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // Parse up the stat file for the proc 861d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich snprintf(buf, 32, "/proc/%d/stat", pid); 871d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich fd = open(buf, O_RDONLY|O_CLOEXEC, 0); 881d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (fd < 0) 891d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich continue; 901d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich len = read(fd, buf, sizeof buf - 1); 911d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich close(fd); 921d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (len < 40) 931d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich continue; 941d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich buf[len] = 0; 951d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich tmp = strrchr(buf, ')'); 961d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (tmp) 971d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich *tmp = 0; 981d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich else 991d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich continue; 1001d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich memset(cmd, 0, sizeof(cmd)); 1011d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich sscanf(buf, "%d (%15c", &ppid, cmd); 1021d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich sscanf(tmp+2, "%c %d", &state, &ppid); 1031d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 1041d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // Skip kthreads 1051d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (pid == 2 || ppid == 2) 1061d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich continue; 1071d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 1081d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (!show_all && pid == 1) 1091d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich continue; 1101d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 1111d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // now get the capabilities 1121d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capng_clear(CAPNG_SELECT_BOTH); 1131d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capng_setpid(pid); 1141d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (capng_get_caps_process()) 1151d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich continue; 1161d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 1171d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // And print out anything with capabilities 1181d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich caps = capng_have_capabilities(CAPNG_SELECT_CAPS); 1191d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (caps > CAPNG_NONE) { 1201d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // Get the effective uid 1211d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich FILE *f; 1221d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich int line; 1231d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich snprintf(buf, 32, "/proc/%d/status", pid); 1241d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich f = fopen(buf, "rte"); 1251d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (f == NULL) 1261d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich euid = 0; 1271d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich else { 1281d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich line = 0; 1291d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich __fsetlocking(f, FSETLOCKING_BYCALLER); 1301d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich while (fgets(buf, sizeof(buf), f)) { 1311d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (line == 0) { 1321d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich line++; 1331d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich continue; 1341d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1351d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (memcmp(buf, "Uid:", 4) == 0) { 1361d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich int id; 1371d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich sscanf(buf, "Uid: %d %d", 1381d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich &id, &euid); 1391d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich break; 1401d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1411d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1421d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich fclose(f); 1431d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1441d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 1451d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich len = read(fd, buf, sizeof buf - 1); 1461d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich close(fd); 1471d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (header == 0) { 1481d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("%-5s %-5s %-10s %-16s %s\n", 1491d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich "ppid", "pid", "name", "command", 1501d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich "capabilities"); 1511d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich header = 1; 1521d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1531d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (euid == 0) { 1541d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // Take short cut for this one 1551d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich name = "root"; 1561d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich uid = 0; 1571d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } else if (euid != uid) { 1581d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // Only look up if name changed 1591d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich p = getpwuid(euid); 1601d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich uid = euid; 1611d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (p) 1621d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich name = p->pw_name; 1631d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich // If not taking this branch, use last val 1641d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1651d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (name) { 1661d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("%-5d %-5d %-10s %-16s ", ppid, pid, 1671d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich name, cmd); 1681d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } else 1691d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("%-5d %-5d %-10d %-16s ", ppid, pid, 1701d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich uid, cmd); 1711d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (caps == CAPNG_PARTIAL) { 1721d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich capng_print_caps_text(CAPNG_PRINT_STDOUT, 1731d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich CAPNG_PERMITTED); 1741d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich if (capng_have_capabilities(CAPNG_SELECT_BOUNDS) 1751d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich == CAPNG_FULL) 1761d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf(" +"); 1771d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("\n"); 1781d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } else 1791d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich printf("full\n"); 1801d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1811d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich } 1821d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich closedir(d); 1831d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich return 0; 1841d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich} 1851d1011a3c5049a7f9eef99d22f3704e4367579ccNick Kralevich 186