summaryrefslogtreecommitdiffstats
path: root/usr.sbin/jail/command.c
diff options
context:
space:
mode:
authorjamie <jamie@FreeBSD.org>2010-11-04 19:32:32 +0000
committerjamie <jamie@FreeBSD.org>2010-11-04 19:32:32 +0000
commit2e7c3af0f17fe5e2c5e6677314eede9143914c5f (patch)
tree315d35d9c0e380e3aa506991521484591351bbdb /usr.sbin/jail/command.c
parenta7a7f45ee7d37f5bd9ccf10c405a51eba7027262 (diff)
downloadFreeBSD-src-2e7c3af0f17fe5e2c5e6677314eede9143914c5f.zip
FreeBSD-src-2e7c3af0f17fe5e2c5e6677314eede9143914c5f.tar.gz
Check unmounts for a mount point of the right FS type.
Diffstat (limited to 'usr.sbin/jail/command.c')
-rw-r--r--usr.sbin/jail/command.c82
1 files changed, 56 insertions, 26 deletions
diff --git a/usr.sbin/jail/command.c b/usr.sbin/jail/command.c
index eca55e3..ac766cb 100644
--- a/usr.sbin/jail/command.c
+++ b/usr.sbin/jail/command.c
@@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
#include <sys/types.h>
#include <sys/event.h>
+#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/user.h>
@@ -69,7 +70,7 @@ static void add_proc(struct cfjail *j, pid_t pid);
static void clear_procs(struct cfjail *j);
static struct cfjail *find_proc(pid_t pid);
static int check_path(struct cfjail *j, const char *pname, const char *path,
- int isfile);
+ int isfile, const char *umount_type);
static struct cfjails sleeping = TAILQ_HEAD_INITIALIZER(sleeping);
static struct cfjails runnable = TAILQ_HEAD_INITIALIZER(runnable);
@@ -207,8 +208,11 @@ run_command(struct cfjail *j, int *plimit, enum intparam comparam)
failed(j);
return -1;
}
- if (check_path(j, j->intparams[comparam]->name, argv[1], 0) < 0)
+ if (check_path(j, j->intparams[comparam]->name, argv[1], 0,
+ down ? argv[2] : NULL) < 0) {
+ failed(j);
return -1;
+ }
if (down) {
argv[4] = NULL;
argv[3] = argv[1];
@@ -238,8 +242,11 @@ run_command(struct cfjail *j, int *plimit, enum intparam comparam)
}
devpath = alloca(strlen(path) + 5);
sprintf(devpath, "%s/dev", path);
- if (check_path(j, "mount.devfs", devpath, 0) < 0)
+ if (check_path(j, "mount.devfs", devpath, 0,
+ down ? "devfs" : NULL) < 0) {
+ failed(j);
return -1;
+ }
if (down) {
argv = alloca(3 * sizeof(char *));
*(const char **)&argv[0] = "/sbin/umount";
@@ -316,8 +323,10 @@ run_command(struct cfjail *j, int *plimit, enum intparam comparam)
consfd = 0;
if (injail &&
(conslog = string_param(j->intparams[IP_EXEC_CONSOLELOG]))) {
- if (check_path(j, "exec.consolelog", conslog, 1) < 0)
+ if (check_path(j, "exec.consolelog", conslog, 1, NULL) < 0) {
+ failed(j);
return -1;
+ }
consfd =
open(conslog, O_WRONLY | O_CREAT | O_APPEND, DEFFILEMODE);
if (consfd < 0) {
@@ -683,9 +692,11 @@ get_user_info(struct cfjail *j, const char *username,
* with no symlinks.
*/
static int
-check_path(struct cfjail *j, const char *pname, const char *path, int isfile)
+check_path(struct cfjail *j, const char *pname, const char *path, int isfile,
+ const char *umount_type)
{
- struct stat st;
+ struct stat st, mpst;
+ struct statfs stfs;
char *tpath, *p;
const char *jailpath;
size_t jplen;
@@ -693,7 +704,6 @@ check_path(struct cfjail *j, const char *pname, const char *path, int isfile)
if (path[0] != '/') {
jail_warnx(j, "%s: %s: not an absolute pathname",
pname, path);
- failed(j);
return -1;
}
/*
@@ -704,30 +714,50 @@ check_path(struct cfjail *j, const char *pname, const char *path, int isfile)
if (jailpath == NULL)
jailpath = "";
jplen = strlen(jailpath);
- if (strncmp(path, jailpath, jplen) || path[jplen] != '/')
- return 0;
- tpath = alloca(strlen(path) + 1);
- strcpy(tpath, path);
- for (p = tpath + jplen; p != NULL; ) {
- p = strchr(p + 1, '/');
- if (p)
- *p = '\0';
- if (lstat(tpath, &st) < 0) {
- if (errno == ENOENT && isfile && !p)
- break;
- jail_warnx(j, "%s: %s: %s", pname, tpath,
+ if (!strncmp(path, jailpath, jplen) && path[jplen] == '/') {
+ tpath = alloca(strlen(path) + 1);
+ strcpy(tpath, path);
+ for (p = tpath + jplen; p != NULL; ) {
+ p = strchr(p + 1, '/');
+ if (p)
+ *p = '\0';
+ if (lstat(tpath, &st) < 0) {
+ if (errno == ENOENT && isfile && !p)
+ break;
+ jail_warnx(j, "%s: %s: %s", pname, tpath,
+ strerror(errno));
+ return -1;
+ }
+ if (S_ISLNK(st.st_mode)) {
+ jail_warnx(j, "%s: %s is a symbolic link",
+ pname, tpath);
+ return -1;
+ }
+ if (p)
+ *p = '/';
+ }
+ }
+ if (umount_type != NULL) {
+ if (stat(path, &st) < 0 || statfs(path, &stfs) < 0) {
+ jail_warnx(j, "%s: %s: %s", pname, path,
strerror(errno));
- failed(j);
return -1;
}
- if (S_ISLNK(st.st_mode)) {
- jail_warnx(j, "%s: %s is a symbolic link",
- pname, tpath);
- failed(j);
+ if (stat(stfs.f_mntonname, &mpst) < 0) {
+ jail_warnx(j, "%s: %s: %s", pname, stfs.f_mntonname,
+ strerror(errno));
+ return -1;
+ }
+ if (st.st_ino != mpst.st_ino) {
+ jail_warnx(j, "%s: %s: not a mount point",
+ pname, path);
+ return -1;
+ }
+ if (strcmp(stfs.f_fstypename, umount_type)) {
+ jail_warnx(j, "%s: %s: not a %s mount",
+ pname, path, umount_type);
return -1;
}
- if (p)
- *p = '/';
}
return 0;
}
OpenPOWER on IntegriCloud