aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2019-07-07 23:44:05 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2019-07-07 23:44:05 +0200
commit35c4d075fc6f2636da8b525ef45843dd569d26f1 (patch)
tree17f7608f16d62cd1c3ef585becbf091a4e68bd62 /src
parentrelocate mountinfo functionality test (diff)
downloadfirejail-35c4d075fc6f2636da8b525ef45843dd569d26f1.tar.gz
firejail-35c4d075fc6f2636da8b525ef45843dd569d26f1.tar.zst
firejail-35c4d075fc6f2636da8b525ef45843dd569d26f1.zip
misc cleanup (safe_fd function)
Diffstat (limited to 'src')
-rw-r--r--src/firejail/util.c54
1 files changed, 21 insertions, 33 deletions
diff --git a/src/firejail/util.c b/src/firejail/util.c
index fff0bbf2f..918077235 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -50,7 +50,7 @@ void errLogExit(char* fmt, ...) {
50 char *msg1; 50 char *msg1;
51 char *msg2 = "Access error"; 51 char *msg2 = "Access error";
52 if (vasprintf(&msg1, fmt, args) != -1 && 52 if (vasprintf(&msg1, fmt, args) != -1 &&
53 asprintf(&msg2, "Access error: pid %d, last mount name:%s dir:%s type:%s - %s", getuid(), m->fsname, m->dir, m->fstype, msg1) != -1) 53 asprintf(&msg2, "Access error: uid %d, last mount name:%s dir:%s type:%s - %s", getuid(), m->fsname, m->dir, m->fstype, msg1) != -1)
54 syslog(LOG_CRIT, "%s", msg2); 54 syslog(LOG_CRIT, "%s", msg2);
55 va_end(args); 55 va_end(args);
56 closelog(); 56 closelog();
@@ -487,7 +487,6 @@ char *line_remove_spaces(const char *buf) {
487 size_t len = strlen(buf); 487 size_t len = strlen(buf);
488 if (len == 0) 488 if (len == 0)
489 return NULL; 489 return NULL;
490 assert(len + 1 != 0 && buf[len] == '\0');
491 490
492 // allocate memory for the new string 491 // allocate memory for the new string
493 char *rv = malloc(len + 1); 492 char *rv = malloc(len + 1);
@@ -554,15 +553,13 @@ char *split_comma(char *str) {
554char *clean_pathname(const char *path) { 553char *clean_pathname(const char *path) {
555 assert(path); 554 assert(path);
556 size_t len = strlen(path); 555 size_t len = strlen(path);
557 assert(len + 1 != 0 && path[len] == '\0');
558
559 char *rv = malloc(len + 1); 556 char *rv = malloc(len + 1);
560 if (!rv) 557 if (!rv)
561 errExit("malloc"); 558 errExit("malloc");
562 559
563 if (len > 0) { 560 if (len > 0) {
564 size_t i, j, cnt; 561 size_t i = 0, j = 0, cnt = 0;
565 for (i = 0, j = 0, cnt = 0; i < len; i++) { 562 for (; i < len; i++) {
566 if (path[i] == '/') 563 if (path[i] == '/')
567 cnt++; 564 cnt++;
568 else 565 else
@@ -1142,56 +1139,47 @@ void disable_file_path(const char *path, const char *file) {
1142 free(fname); 1139 free(fname);
1143} 1140}
1144 1141
1145// The returned file descriptor should be suitable for privileged operations on 1142// open file without following any symbolic link
1146// user controlled paths 1143// returns a file descriptor on success, or -1 if a symlink is found
1147int safe_fd(const char *path, int flags) { 1144int safe_fd(const char *path, int flags) {
1148 assert(path); 1145 assert(path);
1149
1150 // reject empty string, relative path
1151 if (*path != '/') 1146 if (*path != '/')
1152 goto errexit; 1147 goto errexit;
1153 // reject ".."
1154 if (strstr(path, "..")) 1148 if (strstr(path, ".."))
1155 goto errexit; 1149 goto errexit;
1156 char *p = strrchr(path, '/');
1157 assert(p);
1158 // reject trailing slash, root directory
1159 if (*(p + 1) == '\0')
1160 goto errexit;
1161 // reject trailing dot
1162 if (*(p + 1) == '.' && *(p + 2) == '\0')
1163 goto errexit;
1164
1165 // work with a copy of path
1166 char *dup = strdup(path);
1167 if (!dup)
1168 errExit("strdup");
1169 1150
1170 int parentfd = open("/", O_PATH|O_DIRECTORY|O_CLOEXEC); 1151 int parentfd = open("/", O_PATH|O_DIRECTORY|O_CLOEXEC);
1171 if (parentfd == -1) 1152 if (parentfd == -1)
1172 errExit("open"); 1153 errExit("open");
1173
1174 // traverse the path and return -1 if a symlink is encountered
1175 int fd = -1; 1154 int fd = -1;
1176 char *current_tok = EMPTY_STRING; 1155
1156 char *last_tok = EMPTY_STRING;
1157 char *dup = strdup(path);
1158 if (!dup)
1159 errExit("strdup");
1177 char *tok = strtok(dup, "/"); 1160 char *tok = strtok(dup, "/");
1178 assert(tok); 1161 if (!tok) { // root directory
1162 free(dup);
1163 return parentfd;
1164 }
1165
1179 while (tok) { 1166 while (tok) {
1180 // open the element, assuming it is a directory; this fails with ENOTDIR if it is a symbolic link 1167 // open the element, assuming it is a directory; this fails with ENOTDIR if it is a symbolic link
1168 // if token is a single dot, the previous directory is reopened
1181 fd = openat(parentfd, tok, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); 1169 fd = openat(parentfd, tok, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC);
1182 if (fd == -1) { 1170 if (fd == -1) {
1183 // if the following token is NULL, the current token is the final path element 1171 // if the following token is NULL, the current token is the final path element
1184 // try again to open it, this time using the passed flags, and return -1 or the descriptor 1172 // try again to open it, this time using the passed flags, and return -1 or the descriptor
1185 current_tok = tok; 1173 last_tok = tok;
1186 tok = strtok(NULL, "/"); 1174 tok = strtok(NULL, "/");
1187 if (!tok) 1175 if (!tok)
1188 fd = openat(parentfd, current_tok, flags|O_NOFOLLOW); 1176 fd = openat(parentfd, last_tok, flags|O_NOFOLLOW);
1189 close(parentfd); 1177 close(parentfd);
1190 free(dup); 1178 free(dup);
1191 return fd; // -1 if open failed 1179 return fd; // -1 if open failed
1192 } 1180 }
1193 // move on to next path segment 1181 // move on to next path segment
1194 current_tok = tok; 1182 last_tok = tok;
1195 tok = strtok(NULL, "/"); 1183 tok = strtok(NULL, "/");
1196 if (tok) { 1184 if (tok) {
1197 close(parentfd); 1185 close(parentfd);
@@ -1202,13 +1190,13 @@ int safe_fd(const char *path, int flags) {
1202 // we are here because the last path element exists and is of file type directory 1190 // we are here because the last path element exists and is of file type directory
1203 // reopen it using the passed flags 1191 // reopen it using the passed flags
1204 close(fd); 1192 close(fd);
1205 fd = openat(parentfd, current_tok, flags|O_NOFOLLOW); 1193 fd = openat(parentfd, last_tok, flags|O_NOFOLLOW);
1206 close(parentfd); 1194 close(parentfd);
1207 free(dup); 1195 free(dup);
1208 return fd; // -1 if open failed 1196 return fd; // -1 if open failed
1209 1197
1210errexit: 1198errexit:
1211 fprintf(stderr, "Error: cannot open \"%s\", invalid filename\n", path); 1199 fprintf(stderr, "Error: cannot open \"%s\": invalid path\n", path);
1212 exit(1); 1200 exit(1);
1213} 1201}
1214 1202