From: Franck Bui Date: Fri, 13 Apr 2018 15:54:09 +0000 (+0200) Subject: tmpfiles: make write_one_file() safe X-Git-Tag: v240~864^2~20 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=551470ecf2bb56d28e30440ca93e07ee5427e3b8;p=thirdparty%2Fsystemd.git tmpfiles: make write_one_file() safe --- diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 28e65502436..36784a3ad9b 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -1271,7 +1271,8 @@ static int path_set_attribute(Item *item, const char *path) { } static int write_one_file(Item *i, const char *path) { - _cleanup_close_ int fd = -1; + _cleanup_close_ int fd = -1, dir_fd = -1; + char *bn; int r; assert(i); @@ -1279,8 +1280,16 @@ static int write_one_file(Item *i, const char *path) { assert(i->argument); assert(i->type == WRITE_FILE); + /* Validate the path and keep the fd on the directory for opening the + * file so we're sure that it can't be changed behind our back. */ + dir_fd = path_open_parent_safe(path); + if (dir_fd < 0) + return dir_fd; + + bn = basename(path); + /* Follows symlinks */ - fd = open(path, O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode); + fd = openat(dir_fd, bn, O_NONBLOCK|O_CLOEXEC|O_WRONLY|O_NOCTTY, i->mode); if (fd < 0) { if (errno == ENOENT) { log_debug_errno(errno, "Not writing missing file \"%s\": %m", path); @@ -1296,7 +1305,7 @@ static int write_one_file(Item *i, const char *path) { if (r < 0) return log_error_errno(r, "Failed to write file \"%s\": %m", path); - return path_set_perms(i, path); + return fd_set_perms(i, fd, NULL); } static int create_file(Item *i, const char *path) {