diff options
author | smitsohu <smitsohu@gmail.com> | 2018-07-16 01:49:46 +0200 |
---|---|---|
committer | smitsohu <smitsohu@gmail.com> | 2018-07-16 01:49:46 +0200 |
commit | d22b46bc8df2842470713341e1fa30e65fcd702f (patch) | |
tree | 45753b74fb52f9bf194925b6e46e13247582c2eb /src | |
parent | minor improvements to previous commit 949b924fba58dc05f1c21d6621f05047be5397f0 (diff) | |
download | firejail-d22b46bc8df2842470713341e1fa30e65fcd702f.tar.gz firejail-d22b46bc8df2842470713341e1fa30e65fcd702f.tar.zst firejail-d22b46bc8df2842470713341e1fa30e65fcd702f.zip |
rework fix for empty spaces in mountinfo fields
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/mountinfo.c | 129 | ||||
-rw-r--r-- | src/firejail/util.c | 104 |
2 files changed, 129 insertions, 104 deletions
diff --git a/src/firejail/mountinfo.c b/src/firejail/mountinfo.c new file mode 100644 index 000000000..4a7816901 --- /dev/null +++ b/src/firejail/mountinfo.c | |||
@@ -0,0 +1,129 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2018 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | |||
21 | #include "firejail.h" | ||
22 | |||
23 | #define MAX_BUF 4096 | ||
24 | static char mbuf[MAX_BUF]; | ||
25 | static MountData mdata; | ||
26 | |||
27 | // Convert octal escape sequence to decimal value | ||
28 | static int read_oct(const char *path) { | ||
29 | int decimal = 0; | ||
30 | int digit, i; | ||
31 | // there are always three octal digits | ||
32 | for (i = 1; i < 4; i++) { | ||
33 | digit = *(path + i); | ||
34 | if (digit < '0' || digit > '7') { | ||
35 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); | ||
36 | exit(1); | ||
37 | } | ||
38 | decimal = (decimal + digit - '0') * 8; | ||
39 | } | ||
40 | decimal /= 8; | ||
41 | return decimal; | ||
42 | } | ||
43 | |||
44 | // Restore empty spaces in pathnames extracted from /proc/self/mountinfo | ||
45 | static void unmangle_path(char *path) { | ||
46 | char *p = strchr(path, '\\'); | ||
47 | if (p) { | ||
48 | if (read_oct(p) == ' ') { | ||
49 | *p = ' '; | ||
50 | int i = 3; | ||
51 | do { | ||
52 | p++; | ||
53 | if (*(p + i) == '\\' && read_oct(p + i) == ' ') { | ||
54 | *p = ' '; | ||
55 | i += 3; | ||
56 | } | ||
57 | else | ||
58 | *p = *(p + i); | ||
59 | } while (*p); | ||
60 | } | ||
61 | } | ||
62 | } | ||
63 | |||
64 | // Get info regarding the last kernel mount operation. | ||
65 | // The return value points to a static area, and will be overwritten by subsequent calls. | ||
66 | // The function does an exit(1) if anything goes wrong. | ||
67 | MountData *get_last_mount(void) { | ||
68 | // open /proc/self/mountinfo | ||
69 | FILE *fp = fopen("/proc/self/mountinfo", "r"); | ||
70 | if (!fp) | ||
71 | goto errexit; | ||
72 | |||
73 | mbuf[0] = '\0'; | ||
74 | while (fgets(mbuf, MAX_BUF, fp)); | ||
75 | fclose(fp); | ||
76 | if (arg_debug) | ||
77 | printf("%s", mbuf); | ||
78 | |||
79 | // extract filesystem name, directory and filesystem type | ||
80 | // examples: | ||
81 | // 587 543 8:1 /tmp /etc rw,relatime master:1 - ext4 /dev/sda1 rw,errors=remount-ro,data=ordered | ||
82 | // mdata.fsname: /tmp | ||
83 | // mdata.dir: /etc | ||
84 | // mdata.fstype: ext4 | ||
85 | // 585 564 0:76 / /home/netblue/.cache rw,nosuid,nodev - tmpfs tmpfs rw | ||
86 | // mdata.fsname: / | ||
87 | // mdata.dir: /home/netblue/.cache | ||
88 | // mdata.fstype: tmpfs | ||
89 | memset(&mdata, 0, sizeof(mdata)); | ||
90 | char *ptr = strtok(mbuf, " "); | ||
91 | if (!ptr) | ||
92 | goto errexit; | ||
93 | |||
94 | int cnt = 1; | ||
95 | while ((ptr = strtok(NULL, " ")) != NULL) { | ||
96 | cnt++; | ||
97 | if (cnt == 4) | ||
98 | mdata.fsname = ptr; | ||
99 | else if (cnt == 5) { | ||
100 | mdata.dir = ptr; | ||
101 | break; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | ptr = strtok(NULL, "-"); | ||
106 | if (!ptr) | ||
107 | goto errexit; | ||
108 | |||
109 | ptr = strtok(NULL, " "); | ||
110 | if (!ptr) | ||
111 | goto errexit; | ||
112 | mdata.fstype = ptr++; | ||
113 | |||
114 | if (mdata.fsname == NULL || | ||
115 | mdata.dir == NULL || | ||
116 | mdata.fstype == NULL) | ||
117 | goto errexit; | ||
118 | |||
119 | unmangle_path(mdata.fsname); | ||
120 | unmangle_path(mdata.dir); | ||
121 | |||
122 | if (arg_debug) | ||
123 | printf("fsname=%s dir=%s fstype=%s\n", mdata.fsname, mdata.dir, mdata.fstype); | ||
124 | return &mdata; | ||
125 | |||
126 | errexit: | ||
127 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); | ||
128 | exit(1); | ||
129 | } | ||
diff --git a/src/firejail/util.c b/src/firejail/util.c index 52db987b7..f634ff700 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -1045,110 +1045,6 @@ void disable_file_path(const char *path, const char *file) { | |||
1045 | free(fname); | 1045 | free(fname); |
1046 | } | 1046 | } |
1047 | 1047 | ||
1048 | // Restore empty spaces in pathnames extracted from /proc/self/mountinfo | ||
1049 | static void unmangle_path(char *path) { | ||
1050 | int i, decimal; | ||
1051 | char *worker; | ||
1052 | |||
1053 | char *p = strchr(path, '\\'); | ||
1054 | while (p) { | ||
1055 | // convert octal to decimal | ||
1056 | decimal = 0; | ||
1057 | for (i = 1; i < 4; i++) { | ||
1058 | worker = p + i; | ||
1059 | // there are always three octal digits | ||
1060 | if (*worker < '0' || *worker > '7') { | ||
1061 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); | ||
1062 | exit(1); | ||
1063 | } | ||
1064 | decimal = (*worker - '0' + decimal) * 8; | ||
1065 | } | ||
1066 | decimal /= 8; | ||
1067 | // do the replacement | ||
1068 | if (decimal == ' ') { | ||
1069 | *p = ' '; | ||
1070 | worker = p; | ||
1071 | do { | ||
1072 | worker++; | ||
1073 | *worker = *(worker + 3); | ||
1074 | } while (*worker); | ||
1075 | } | ||
1076 | |||
1077 | p = strchr(p + 1, '\\'); | ||
1078 | } | ||
1079 | } | ||
1080 | |||
1081 | #define MAX_BUF 4096 | ||
1082 | static char mbuf[MAX_BUF]; | ||
1083 | static MountData mdata; | ||
1084 | |||
1085 | // Get info regarding the last kernel mount operation. | ||
1086 | // The return value points to a static area, and will be overwritten by subsequent calls. | ||
1087 | // The function does an exit(1) if anything goes wrong. | ||
1088 | MountData *get_last_mount(void) { | ||
1089 | // open /proc/self/mountinfo | ||
1090 | FILE *fp = fopen("/proc/self/mountinfo", "r"); | ||
1091 | if (!fp) | ||
1092 | goto errexit; | ||
1093 | |||
1094 | mbuf[0] = '\0'; | ||
1095 | while (fgets(mbuf, MAX_BUF, fp)); | ||
1096 | fclose(fp); | ||
1097 | if (arg_debug) | ||
1098 | printf("%s", mbuf); | ||
1099 | |||
1100 | // extract filesystem name, directory and filesystem type | ||
1101 | // examples: | ||
1102 | // 587 543 8:1 /tmp /etc rw,relatime master:1 - ext4 /dev/sda1 rw,errors=remount-ro,data=ordered | ||
1103 | // mdata.fsname: /tmp | ||
1104 | // mdata.dir: /etc | ||
1105 | // mdata.fstype: ext4 | ||
1106 | // 585 564 0:76 / /home/netblue/.cache rw,nosuid,nodev - tmpfs tmpfs rw | ||
1107 | // mdata.fsname: / | ||
1108 | // mdata.dir: /home/netblue/.cache | ||
1109 | // mdata.fstype: tmpfs | ||
1110 | memset(&mdata, 0, sizeof(mdata)); | ||
1111 | char *ptr = strtok(mbuf, " "); | ||
1112 | if (!ptr) | ||
1113 | goto errexit; | ||
1114 | |||
1115 | int cnt = 1; | ||
1116 | while ((ptr = strtok(NULL, " ")) != NULL) { | ||
1117 | cnt++; | ||
1118 | if (cnt == 4) | ||
1119 | mdata.fsname = ptr; | ||
1120 | else if (cnt == 5) { | ||
1121 | mdata.dir = ptr; | ||
1122 | break; | ||
1123 | } | ||
1124 | } | ||
1125 | |||
1126 | ptr = strtok(NULL, "-"); | ||
1127 | if (!ptr) | ||
1128 | goto errexit; | ||
1129 | |||
1130 | ptr = strtok(NULL, " "); | ||
1131 | if (!ptr) | ||
1132 | goto errexit; | ||
1133 | mdata.fstype = ptr++; | ||
1134 | |||
1135 | if (mdata.fsname == NULL || | ||
1136 | mdata.dir == NULL || | ||
1137 | mdata.fstype == NULL) | ||
1138 | goto errexit; | ||
1139 | |||
1140 | unmangle_path(mdata.fsname); | ||
1141 | unmangle_path(mdata.dir); | ||
1142 | |||
1143 | if (arg_debug) | ||
1144 | printf("fsname=%s dir=%s fstype=%s\n", mdata.fsname, mdata.dir, mdata.fstype); | ||
1145 | return &mdata; | ||
1146 | |||
1147 | errexit: | ||
1148 | fprintf(stderr, "Error: cannot read /proc/self/mountinfo\n"); | ||
1149 | exit(1); | ||
1150 | } | ||
1151 | |||
1152 | // The returned file descriptor should be suitable for privileged operations on | 1048 | // The returned file descriptor should be suitable for privileged operations on |
1153 | // user controlled paths. Passed flags are ignored if path is a top level directory. | 1049 | // user controlled paths. Passed flags are ignored if path is a top level directory. |
1154 | int safe_fd(const char *path, int flags) { | 1050 | int safe_fd(const char *path, int flags) { |