+++ /dev/null
-/*
- * Temporary debug code to find processes locking internal cryptsetup devices.
- * This code is intended to run only in debug mode.
- *
- * inspired by psmisc/fuser proc scanning code
- *
- * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include "libcryptsetup.h"
-#include "internal.h"
-
-#define MAX_PATHNAME 1024
-#define MAX_SHORTNAME 64
-
-static int numeric_name(const char *name)
-{
- return (name[0] < '0' || name[0] > '9') ? 0 : 1;
-}
-
-static int check_pid(const pid_t pid, const char *dev_name, const char *short_dev_name)
-{
- char dirpath[MAX_SHORTNAME], fdpath[MAX_SHORTNAME], linkpath[MAX_PATHNAME];
- DIR *dirp;
- struct dirent *direntry;
- ssize_t len;
- int r = 0;
-
- snprintf(dirpath, sizeof(dirpath), "/proc/%d/fd", pid);
-
- if (!(dirp = opendir(dirpath)))
- return r;
-
- while ((direntry = readdir(dirp))) {
- if (!numeric_name(direntry->d_name))
- continue;
-
- snprintf(fdpath, sizeof(fdpath), "/proc/%d/fd/%s", pid, direntry->d_name);
-
- if ((len = readlink(fdpath, linkpath, MAX_PATHNAME-1)) < 0)
- break;
- linkpath[len] = '\0';
-
- if (!strcmp(dev_name, linkpath)) {
- r = 1;
- break;
- }
-
- if (!strcmp(short_dev_name, linkpath)) {
- r = 2;
- break;
- }
- }
- closedir(dirp);
- return r;
-}
-
-static int read_proc_info(const pid_t pid, pid_t *ppid, char *name, int max_size)
-{
- char path[MAX_SHORTNAME], info[max_size], c;
- int fd, xpid, r = 0;
-
- snprintf(path, sizeof(path), "/proc/%u/stat", pid);
- if ((fd = open(path, O_RDONLY)) < 0)
- return 0;
-
- if (read(fd, info, max_size) > 0 &&
- sscanf(info, "%d %s %c %d", &xpid, name, &c, ppid) == 4)
- r = 1;
-
- if (!r) {
- *ppid = 0;
- name[0] = '\0';
- }
- close(fd);
- return r;
-}
-
-static void report_proc(const pid_t pid, const char *dev_name)
-{
- char name[MAX_PATHNAME], name2[MAX_PATHNAME];
- pid_t ppid, ppid2;
-
- if (read_proc_info(pid, &ppid, name, MAX_PATHNAME) &&
- read_proc_info(ppid, &ppid2, name2, MAX_PATHNAME))
- log_dbg("WARNING: Process PID %u %s [PPID %u %s] spying on internal device %s.",
- pid, name, ppid, name2, dev_name);
-}
-
-void debug_processes_using_device(const char *dm_name)
-{
- char short_dev_name[MAX_SHORTNAME], dev_name[MAX_PATHNAME];
- DIR *proc_dir;
- struct dirent *proc_dentry;
- struct stat st;
- pid_t pid;
-
- if (crypt_get_debug_level() != CRYPT_LOG_DEBUG)
- return;
-
- snprintf(dev_name, sizeof(dev_name), "/dev/mapper/%s", dm_name);
- if (stat(dev_name, &st) || !S_ISBLK(st.st_mode))
- return;
- snprintf(short_dev_name, sizeof(short_dev_name), "/dev/dm-%u", minor(st.st_rdev));
-
- if (!(proc_dir = opendir("/proc")))
- return;
-
- while ((proc_dentry = readdir(proc_dir))) {
- if (!numeric_name(proc_dentry->d_name))
- continue;
-
- pid = atoi(proc_dentry->d_name);
- switch(check_pid(pid, dev_name, short_dev_name)) {
- case 1: report_proc(pid, dev_name);
- break;
- case 2: report_proc(pid, short_dev_name);
- default:
- break;
- }
- }
- closedir(proc_dir);
-}