chiark / gitweb /
cgroup, unit, fragment parser: make use of new firewall functions
[elogind.git] / src / basic / fs-util.c
1 /***
2   This file is part of systemd.
3
4   Copyright 2010 Lennart Poettering
5
6   systemd is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as published by
8   the Free Software Foundation; either version 2.1 of the License, or
9   (at your option) any later version.
10
11   systemd is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   Lesser General Public License for more details.
15
16   You should have received a copy of the GNU Lesser General Public License
17   along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include <errno.h>
21 #include <stddef.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 #include <linux/magic.h>
27 #include <time.h>
28 #include <unistd.h>
29
30 #include "alloc-util.h"
31 #include "dirent-util.h"
32 #include "fd-util.h"
33 #include "fileio.h"
34 #include "fs-util.h"
35 //#include "log.h"
36 //#include "macro.h"
37 //#include "missing.h"
38 #include "mkdir.h"
39 #include "parse-util.h"
40 #include "path-util.h"
41 #include "process-util.h"
42 #include "stat-util.h"
43 #include "stdio-util.h"
44 #include "string-util.h"
45 #include "strv.h"
46 //#include "time-util.h"
47 #include "user-util.h"
48 #include "util.h"
49
50 int unlink_noerrno(const char *path) {
51         PROTECT_ERRNO;
52         int r;
53
54         r = unlink(path);
55         if (r < 0)
56                 return -errno;
57
58         return 0;
59 }
60
61 #if 0 /// UNNEEDED by elogind
62 int rmdir_parents(const char *path, const char *stop) {
63         size_t l;
64         int r = 0;
65
66         assert(path);
67         assert(stop);
68
69         l = strlen(path);
70
71         /* Skip trailing slashes */
72         while (l > 0 && path[l-1] == '/')
73                 l--;
74
75         while (l > 0) {
76                 char *t;
77
78                 /* Skip last component */
79                 while (l > 0 && path[l-1] != '/')
80                         l--;
81
82                 /* Skip trailing slashes */
83                 while (l > 0 && path[l-1] == '/')
84                         l--;
85
86                 if (l <= 0)
87                         break;
88
89                 t = strndup(path, l);
90                 if (!t)
91                         return -ENOMEM;
92
93                 if (path_startswith(stop, t)) {
94                         free(t);
95                         return 0;
96                 }
97
98                 r = rmdir(t);
99                 free(t);
100
101                 if (r < 0)
102                         if (errno != ENOENT)
103                                 return -errno;
104         }
105
106         return 0;
107 }
108
109
110 int rename_noreplace(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
111         struct stat buf;
112         int ret;
113
114         ret = renameat2(olddirfd, oldpath, newdirfd, newpath, RENAME_NOREPLACE);
115         if (ret >= 0)
116                 return 0;
117
118         /* renameat2() exists since Linux 3.15, btrfs added support for it later.
119          * If it is not implemented, fallback to another method. */
120         if (!IN_SET(errno, EINVAL, ENOSYS))
121                 return -errno;
122
123         /* The link()/unlink() fallback does not work on directories. But
124          * renameat() without RENAME_NOREPLACE gives the same semantics on
125          * directories, except when newpath is an *empty* directory. This is
126          * good enough. */
127         ret = fstatat(olddirfd, oldpath, &buf, AT_SYMLINK_NOFOLLOW);
128         if (ret >= 0 && S_ISDIR(buf.st_mode)) {
129                 ret = renameat(olddirfd, oldpath, newdirfd, newpath);
130                 return ret >= 0 ? 0 : -errno;
131         }
132
133         /* If it is not a directory, use the link()/unlink() fallback. */
134         ret = linkat(olddirfd, oldpath, newdirfd, newpath, 0);
135         if (ret < 0)
136                 return -errno;
137
138         ret = unlinkat(olddirfd, oldpath, 0);
139         if (ret < 0) {
140                 /* backup errno before the following unlinkat() alters it */
141                 ret = errno;
142                 (void) unlinkat(newdirfd, newpath, 0);
143                 errno = ret;
144                 return -errno;
145         }
146
147         return 0;
148 }
149 #endif // 0
150
151 int readlinkat_malloc(int fd, const char *p, char **ret) {
152         size_t l = 100;
153         int r;
154
155         assert(p);
156         assert(ret);
157
158         for (;;) {
159                 char *c;
160                 ssize_t n;
161
162                 c = new(char, l);
163                 if (!c)
164                         return -ENOMEM;
165
166                 n = readlinkat(fd, p, c, l-1);
167                 if (n < 0) {
168                         r = -errno;
169                         free(c);
170                         return r;
171                 }
172
173                 if ((size_t) n < l-1) {
174                         c[n] = 0;
175                         *ret = c;
176                         return 0;
177                 }
178
179                 free(c);
180                 l *= 2;
181         }
182 }
183
184 int readlink_malloc(const char *p, char **ret) {
185         return readlinkat_malloc(AT_FDCWD, p, ret);
186 }
187
188 #if 0 /// UNNEEDED by elogind
189 int readlink_value(const char *p, char **ret) {
190         _cleanup_free_ char *link = NULL;
191         char *value;
192         int r;
193
194         r = readlink_malloc(p, &link);
195         if (r < 0)
196                 return r;
197
198         value = basename(link);
199         if (!value)
200                 return -ENOENT;
201
202         value = strdup(value);
203         if (!value)
204                 return -ENOMEM;
205
206         *ret = value;
207
208         return 0;
209 }
210 #endif // 0
211
212 int readlink_and_make_absolute(const char *p, char **r) {
213         _cleanup_free_ char *target = NULL;
214         char *k;
215         int j;
216
217         assert(p);
218         assert(r);
219
220         j = readlink_malloc(p, &target);
221         if (j < 0)
222                 return j;
223
224         k = file_in_same_dir(p, target);
225         if (!k)
226                 return -ENOMEM;
227
228         *r = k;
229         return 0;
230 }
231
232 #if 0 /// UNNEEDED by elogind
233 int readlink_and_canonicalize(const char *p, const char *root, char **ret) {
234         char *t, *s;
235         int r;
236
237         assert(p);
238         assert(ret);
239
240         r = readlink_and_make_absolute(p, &t);
241         if (r < 0)
242                 return r;
243
244         r = chase_symlinks(t, root, 0, &s);
245         if (r < 0)
246                 /* If we can't follow up, then let's return the original string, slightly cleaned up. */
247                 *ret = path_kill_slashes(t);
248         else {
249                 *ret = s;
250                 free(t);
251         }
252
253         return 0;
254 }
255
256 int readlink_and_make_absolute_root(const char *root, const char *path, char **ret) {
257         _cleanup_free_ char *target = NULL, *t = NULL;
258         const char *full;
259         int r;
260
261         full = prefix_roota(root, path);
262         r = readlink_malloc(full, &target);
263         if (r < 0)
264                 return r;
265
266         t = file_in_same_dir(path, target);
267         if (!t)
268                 return -ENOMEM;
269
270         *ret = t;
271         t = NULL;
272
273         return 0;
274 }
275 #endif // 0
276
277 int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
278         assert(path);
279
280         /* Under the assumption that we are running privileged we
281          * first change the access mode and only then hand out
282          * ownership to avoid a window where access is too open. */
283
284         if (mode != MODE_INVALID)
285                 if (chmod(path, mode) < 0)
286                         return -errno;
287
288         if (uid != UID_INVALID || gid != GID_INVALID)
289                 if (chown(path, uid, gid) < 0)
290                         return -errno;
291
292         return 0;
293 }
294
295 int fchmod_umask(int fd, mode_t m) {
296         mode_t u;
297         int r;
298
299         u = umask(0777);
300         r = fchmod(fd, m & (~u)) < 0 ? -errno : 0;
301         umask(u);
302
303         return r;
304 }
305
306 int fd_warn_permissions(const char *path, int fd) {
307         struct stat st;
308
309         if (fstat(fd, &st) < 0)
310                 return -errno;
311
312         if (st.st_mode & 0111)
313                 log_warning("Configuration file %s is marked executable. Please remove executable permission bits. Proceeding anyway.", path);
314
315         if (st.st_mode & 0002)
316                 log_warning("Configuration file %s is marked world-writable. Please remove world writability permission bits. Proceeding anyway.", path);
317
318         if (getpid_cached() == 1 && (st.st_mode & 0044) != 0044)
319                 log_warning("Configuration file %s is marked world-inaccessible. This has no effect as configuration data is accessible via APIs without restrictions. Proceeding anyway.", path);
320
321         return 0;
322 }
323
324 int touch_file(const char *path, bool parents, usec_t stamp, uid_t uid, gid_t gid, mode_t mode) {
325         _cleanup_close_ int fd;
326         int r;
327
328         assert(path);
329
330         if (parents)
331                 mkdir_parents(path, 0755);
332
333         fd = open(path, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
334                         (mode == 0 || mode == MODE_INVALID) ? 0644 : mode);
335         if (fd < 0)
336                 return -errno;
337
338         if (mode != MODE_INVALID) {
339                 r = fchmod(fd, mode);
340                 if (r < 0)
341                         return -errno;
342         }
343
344         if (uid != UID_INVALID || gid != GID_INVALID) {
345                 r = fchown(fd, uid, gid);
346                 if (r < 0)
347                         return -errno;
348         }
349
350         if (stamp != USEC_INFINITY) {
351                 struct timespec ts[2];
352
353                 timespec_store(&ts[0], stamp);
354                 ts[1] = ts[0];
355                 r = futimens(fd, ts);
356         } else
357                 r = futimens(fd, NULL);
358         if (r < 0)
359                 return -errno;
360
361         return 0;
362 }
363
364 int touch(const char *path) {
365         return touch_file(path, false, USEC_INFINITY, UID_INVALID, GID_INVALID, MODE_INVALID);
366 }
367
368 #if 0 /// UNNEEDED by elogind
369 int symlink_idempotent(const char *from, const char *to) {
370         _cleanup_free_ char *p = NULL;
371         int r;
372
373         assert(from);
374         assert(to);
375
376         if (symlink(from, to) < 0) {
377                 if (errno != EEXIST)
378                         return -errno;
379
380                 r = readlink_malloc(to, &p);
381                 if (r < 0)
382                         return r;
383
384                 if (!streq(p, from))
385                         return -EINVAL;
386         }
387
388         return 0;
389 }
390
391 int symlink_atomic(const char *from, const char *to) {
392         _cleanup_free_ char *t = NULL;
393         int r;
394
395         assert(from);
396         assert(to);
397
398         r = tempfn_random(to, NULL, &t);
399         if (r < 0)
400                 return r;
401
402         if (symlink(from, t) < 0)
403                 return -errno;
404
405         if (rename(t, to) < 0) {
406                 unlink_noerrno(t);
407                 return -errno;
408         }
409
410         return 0;
411 }
412
413 int mknod_atomic(const char *path, mode_t mode, dev_t dev) {
414         _cleanup_free_ char *t = NULL;
415         int r;
416
417         assert(path);
418
419         r = tempfn_random(path, NULL, &t);
420         if (r < 0)
421                 return r;
422
423         if (mknod(t, mode, dev) < 0)
424                 return -errno;
425
426         if (rename(t, path) < 0) {
427                 unlink_noerrno(t);
428                 return -errno;
429         }
430
431         return 0;
432 }
433
434 int mkfifo_atomic(const char *path, mode_t mode) {
435         _cleanup_free_ char *t = NULL;
436         int r;
437
438         assert(path);
439
440         r = tempfn_random(path, NULL, &t);
441         if (r < 0)
442                 return r;
443
444         if (mkfifo(t, mode) < 0)
445                 return -errno;
446
447         if (rename(t, path) < 0) {
448                 unlink_noerrno(t);
449                 return -errno;
450         }
451
452         return 0;
453 }
454 #endif // 0
455
456 int get_files_in_directory(const char *path, char ***list) {
457         _cleanup_closedir_ DIR *d = NULL;
458         struct dirent *de;
459         size_t bufsize = 0, n = 0;
460         _cleanup_strv_free_ char **l = NULL;
461
462         assert(path);
463
464         /* Returns all files in a directory in *list, and the number
465          * of files as return value. If list is NULL returns only the
466          * number. */
467
468         d = opendir(path);
469         if (!d)
470                 return -errno;
471
472         FOREACH_DIRENT_ALL(de, d, return -errno) {
473                 dirent_ensure_type(d, de);
474
475                 if (!dirent_is_file(de))
476                         continue;
477
478                 if (list) {
479                         /* one extra slot is needed for the terminating NULL */
480                         if (!GREEDY_REALLOC(l, bufsize, n + 2))
481                                 return -ENOMEM;
482
483                         l[n] = strdup(de->d_name);
484                         if (!l[n])
485                                 return -ENOMEM;
486
487                         l[++n] = NULL;
488                 } else
489                         n++;
490         }
491
492         if (list) {
493                 *list = l;
494                 l = NULL; /* avoid freeing */
495         }
496
497         return n;
498 }
499
500 static int getenv_tmp_dir(const char **ret_path) {
501         const char *n;
502         int r, ret = 0;
503
504         assert(ret_path);
505
506         /* We use the same order of environment variables python uses in tempfile.gettempdir():
507          * https://docs.python.org/3/library/tempfile.html#tempfile.gettempdir */
508         FOREACH_STRING(n, "TMPDIR", "TEMP", "TMP") {
509                 const char *e;
510
511                 e = secure_getenv(n);
512                 if (!e)
513                         continue;
514                 if (!path_is_absolute(e)) {
515                         r = -ENOTDIR;
516                         goto next;
517                 }
518                 if (!path_is_safe(e)) {
519                         r = -EPERM;
520                         goto next;
521                 }
522
523                 r = is_dir(e, true);
524                 if (r < 0)
525                         goto next;
526                 if (r == 0) {
527                         r = -ENOTDIR;
528                         goto next;
529                 }
530
531                 *ret_path = e;
532                 return 1;
533
534         next:
535                 /* Remember first error, to make this more debuggable */
536                 if (ret >= 0)
537                         ret = r;
538         }
539
540         if (ret < 0)
541                 return ret;
542
543         *ret_path = NULL;
544         return ret;
545 }
546
547 static int tmp_dir_internal(const char *def, const char **ret) {
548         const char *e;
549         int r, k;
550
551         assert(def);
552         assert(ret);
553
554         r = getenv_tmp_dir(&e);
555         if (r > 0) {
556                 *ret = e;
557                 return 0;
558         }
559
560         k = is_dir(def, true);
561         if (k == 0)
562                 k = -ENOTDIR;
563         if (k < 0)
564                 return r < 0 ? r : k;
565
566         *ret = def;
567         return 0;
568 }
569
570 #if 0 /// UNNEEDED by elogind
571 int var_tmp_dir(const char **ret) {
572
573         /* Returns the location for "larger" temporary files, that is backed by physical storage if available, and thus
574          * even might survive a boot: /var/tmp. If $TMPDIR (or related environment variables) are set, its value is
575          * returned preferably however. Note that both this function and tmp_dir() below are affected by $TMPDIR,
576          * making it a variable that overrides all temporary file storage locations. */
577
578         return tmp_dir_internal("/var/tmp", ret);
579 }
580 #endif // 0
581
582 int tmp_dir(const char **ret) {
583
584         /* Similar to var_tmp_dir() above, but returns the location for "smaller" temporary files, which is usually
585          * backed by an in-memory file system: /tmp. */
586
587         return tmp_dir_internal("/tmp", ret);
588 }
589
590 #if 0 /// UNNEEDED by elogind
591 int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
592         char path[strlen("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
593         int r;
594
595         /* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
596         xsprintf(path, "/proc/self/fd/%i", what);
597
598         r = inotify_add_watch(fd, path, mask);
599         if (r < 0)
600                 return -errno;
601
602         return r;
603 }
604 #endif // 0
605
606 int chase_symlinks(const char *path, const char *original_root, unsigned flags, char **ret) {
607         _cleanup_free_ char *buffer = NULL, *done = NULL, *root = NULL;
608         _cleanup_close_ int fd = -1;
609         unsigned max_follow = 32; /* how many symlinks to follow before giving up and returning ELOOP */
610         bool exists = true;
611         char *todo;
612         int r;
613
614         assert(path);
615
616         /* This is a lot like canonicalize_file_name(), but takes an additional "root" parameter, that allows following
617          * symlinks relative to a root directory, instead of the root of the host.
618          *
619          * Note that "root" primarily matters if we encounter an absolute symlink. It is also used when following
620          * relative symlinks to ensure they cannot be used to "escape" the root directory. The path parameter passed is
621          * assumed to be already prefixed by it, except if the CHASE_PREFIX_ROOT flag is set, in which case it is first
622          * prefixed accordingly.
623          *
624          * Algorithmically this operates on two path buffers: "done" are the components of the path we already
625          * processed and resolved symlinks, "." and ".." of. "todo" are the components of the path we still need to
626          * process. On each iteration, we move one component from "todo" to "done", processing it's special meaning
627          * each time. The "todo" path always starts with at least one slash, the "done" path always ends in no
628          * slash. We always keep an O_PATH fd to the component we are currently processing, thus keeping lookup races
629          * at a minimum.
630          *
631          * Suggested usage: whenever you want to canonicalize a path, use this function. Pass the absolute path you got
632          * as-is: fully qualified and relative to your host's root. Optionally, specify the root parameter to tell this
633          * function what to do when encountering a symlink with an absolute path as directory: prefix it by the
634          * specified path.
635          *
636          * Note: there's also chase_symlinks_prefix() (see below), which as first step prefixes the passed path by the
637          * passed root. */
638
639         if (original_root) {
640                 r = path_make_absolute_cwd(original_root, &root);
641                 if (r < 0)
642                         return r;
643
644                 if (flags & CHASE_PREFIX_ROOT)
645                         path = prefix_roota(root, path);
646         }
647
648         r = path_make_absolute_cwd(path, &buffer);
649         if (r < 0)
650                 return r;
651
652         fd = open("/", O_CLOEXEC|O_NOFOLLOW|O_PATH);
653         if (fd < 0)
654                 return -errno;
655
656         todo = buffer;
657         for (;;) {
658                 _cleanup_free_ char *first = NULL;
659                 _cleanup_close_ int child = -1;
660                 struct stat st;
661                 size_t n, m;
662
663                 /* Determine length of first component in the path */
664                 n = strspn(todo, "/");                  /* The slashes */
665                 m = n + strcspn(todo + n, "/");         /* The entire length of the component */
666
667                 /* Extract the first component. */
668                 first = strndup(todo, m);
669                 if (!first)
670                         return -ENOMEM;
671
672                 todo += m;
673
674                 /* Just a single slash? Then we reached the end. */
675                 if (isempty(first) || path_equal(first, "/"))
676                         break;
677
678                 /* Just a dot? Then let's eat this up. */
679                 if (path_equal(first, "/."))
680                         continue;
681
682                 /* Two dots? Then chop off the last bit of what we already found out. */
683                 if (path_equal(first, "/..")) {
684                         _cleanup_free_ char *parent = NULL;
685                         int fd_parent = -1;
686
687                         /* If we already are at the top, then going up will not change anything. This is in-line with
688                          * how the kernel handles this. */
689                         if (isempty(done) || path_equal(done, "/"))
690                                 continue;
691
692                         parent = dirname_malloc(done);
693                         if (!parent)
694                                 return -ENOMEM;
695
696                         /* Don't allow this to leave the root dir.  */
697                         if (root &&
698                             path_startswith(done, root) &&
699                             !path_startswith(parent, root))
700                                 continue;
701
702                         free_and_replace(done, parent);
703
704                         fd_parent = openat(fd, "..", O_CLOEXEC|O_NOFOLLOW|O_PATH);
705                         if (fd_parent < 0)
706                                 return -errno;
707
708                         safe_close(fd);
709                         fd = fd_parent;
710
711                         continue;
712                 }
713
714                 /* Otherwise let's see what this is. */
715                 child = openat(fd, first + n, O_CLOEXEC|O_NOFOLLOW|O_PATH);
716                 if (child < 0) {
717
718                         if (errno == ENOENT &&
719                             (flags & CHASE_NONEXISTENT) &&
720                             (isempty(todo) || path_is_safe(todo))) {
721
722                                 /* If CHASE_NONEXISTENT is set, and the path does not exist, then that's OK, return
723                                  * what we got so far. But don't allow this if the remaining path contains "../ or "./"
724                                  * or something else weird. */
725
726                                 if (!strextend(&done, first, todo, NULL))
727                                         return -ENOMEM;
728
729                                 exists = false;
730                                 break;
731                         }
732
733                         return -errno;
734                 }
735
736                 if (fstat(child, &st) < 0)
737                         return -errno;
738                 if ((flags & CHASE_NO_AUTOFS) &&
739                     fd_check_fstype(child, AUTOFS_SUPER_MAGIC) > 0)
740                         return -EREMOTE;
741
742                 if (S_ISLNK(st.st_mode)) {
743                         char *joined;
744
745                         _cleanup_free_ char *destination = NULL;
746
747                         /* This is a symlink, in this case read the destination. But let's make sure we don't follow
748                          * symlinks without bounds. */
749                         if (--max_follow <= 0)
750                                 return -ELOOP;
751
752                         r = readlinkat_malloc(fd, first + n, &destination);
753                         if (r < 0)
754                                 return r;
755                         if (isempty(destination))
756                                 return -EINVAL;
757
758                         if (path_is_absolute(destination)) {
759
760                                 /* An absolute destination. Start the loop from the beginning, but use the root
761                                  * directory as base. */
762
763                                 safe_close(fd);
764                                 fd = open(root ?: "/", O_CLOEXEC|O_NOFOLLOW|O_PATH);
765                                 if (fd < 0)
766                                         return -errno;
767
768                                 free(done);
769
770                                 /* Note that we do not revalidate the root, we take it as is. */
771                                 if (isempty(root))
772                                         done = NULL;
773                                 else {
774                                         done = strdup(root);
775                                         if (!done)
776                                                 return -ENOMEM;
777                                 }
778
779                         }
780
781                         /* Prefix what's left to do with what we just read, and start the loop again,
782                          * but remain in the current directory. */
783
784                         joined = strjoin("/", destination, todo);
785                         if (!joined)
786                                 return -ENOMEM;
787
788                         free(buffer);
789                         todo = buffer = joined;
790
791                         continue;
792                 }
793
794                 /* If this is not a symlink, then let's just add the name we read to what we already verified. */
795                 if (!done) {
796                         done = first;
797                         first = NULL;
798                 } else {
799                         if (!strextend(&done, first, NULL))
800                                 return -ENOMEM;
801                 }
802
803                 /* And iterate again, but go one directory further down. */
804                 safe_close(fd);
805                 fd = child;
806                 child = -1;
807         }
808
809         if (!done) {
810                 /* Special case, turn the empty string into "/", to indicate the root directory. */
811                 done = strdup("/");
812                 if (!done)
813                         return -ENOMEM;
814         }
815
816         if (ret) {
817                 *ret = done;
818                 done = NULL;
819         }
820
821         return exists;
822 }