From: Lennart Poettering Date: Mon, 1 Feb 2021 16:45:25 +0000 (+0100) Subject: copy: tighten destination checks when copying files X-Git-Tag: v250-rc1~887^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=2f782044986a30bf73f1fe00209dbd204b3efe33;p=thirdparty%2Fsystemd.git copy: tighten destination checks when copying files let's make sure we only operate on regular files when copying files. Also, make sure to copy file attributes only over if target is a regular file (so that copying a file to /dev/null won't alter the access mode/ownership of that device node...) --- diff --git a/src/shared/copy.c b/src/shared/copy.c index 27aa3b29387..bf02a89b514 100644 --- a/src/shared/copy.c +++ b/src/shared/copy.c @@ -1026,6 +1026,7 @@ int copy_file_fd_full( void *userdata) { _cleanup_close_ int fdf = -1; + struct stat st; int r; assert(from); @@ -1035,12 +1036,23 @@ int copy_file_fd_full( if (fdf < 0) return -errno; + r = fd_verify_regular(fdf); + if (r < 0) + return r; + + if (fstat(fdt, &st) < 0) + return -errno; + r = copy_bytes_full(fdf, fdt, UINT64_MAX, copy_flags, NULL, NULL, progress_bytes, userdata); + if (r < 0) + return r; - (void) copy_times(fdf, fdt, copy_flags); - (void) copy_xattr(fdf, fdt); + if (S_ISREG(fdt)) { + (void) copy_times(fdf, fdt, copy_flags); + (void) copy_xattr(fdf, fdt); + } - return r; + return 0; } int copy_file_full( @@ -1065,9 +1077,12 @@ int copy_file_full( if (fdf < 0) return -errno; - if (mode == MODE_INVALID) - if (fstat(fdf, &st) < 0) - return -errno; + if (fstat(fdf, &st) < 0) + return -errno; + + r = stat_verify_regular(&st); + if (r < 0) + return r; RUN_WITH_UMASK(0000) { if (copy_flags & COPY_MAC_CREATE) { @@ -1083,6 +1098,12 @@ int copy_file_full( return -errno; } + if (!FLAGS_SET(flags, O_EXCL)) { /* if O_EXCL was used we created the thing as regular file, no need to check again */ + r = fd_verify_regular(fdt); + if (r < 0) + goto fail; + } + if (chattr_mask != 0) (void) chattr_fd(fdt, chattr_flags, chattr_mask & CHATTR_EARLY_FL, NULL);