stat-util: use stat_verify_xyz() and friends more (#41613)
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "device-nodes.h"
|
||||
#include "path-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-util.h"
|
||||
#include "utf8.h"
|
||||
@@ -63,6 +64,7 @@ int encode_devnode_name(const char *str, char *str_enc, size_t len) {
|
||||
|
||||
int devnode_same(const char *a, const char *b) {
|
||||
struct stat sa, sb;
|
||||
int r;
|
||||
|
||||
assert(a);
|
||||
assert(b);
|
||||
@@ -72,13 +74,15 @@ int devnode_same(const char *a, const char *b) {
|
||||
|
||||
if (stat(a, &sa) < 0)
|
||||
return -errno;
|
||||
r = stat_verify_device_node(&sa);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (stat(b, &sb) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISBLK(sa.st_mode) && !S_ISCHR(sa.st_mode))
|
||||
return -ENODEV;
|
||||
if (!S_ISBLK(sb.st_mode) && !S_ISCHR(sb.st_mode))
|
||||
return -ENODEV;
|
||||
r = stat_verify_device_node(&sb);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (((sa.st_mode ^ sb.st_mode) & S_IFMT) != 0) /* both inode same device node type? */
|
||||
return false;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "path-util.h"
|
||||
#include "process-util.h"
|
||||
#include "set.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
@@ -115,8 +116,9 @@ static int add_locales_from_archive(Set *locales) {
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISREG(st.st_mode))
|
||||
return -EBADMSG;
|
||||
r = stat_verify_regular(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (st.st_size < (off_t) sizeof(struct locarhead))
|
||||
return -EBADMSG;
|
||||
|
||||
+66
-4
@@ -145,6 +145,9 @@ int stat_verify_symlink(const struct stat *st) {
|
||||
}
|
||||
|
||||
int fd_verify_symlink(int fd) {
|
||||
if (IN_SET(fd, AT_FDCWD, XAT_FDROOT))
|
||||
return -EISDIR;
|
||||
|
||||
return verify_stat_at(fd, /* path= */ NULL, /* follow= */ false, stat_verify_symlink, /* verify= */ true);
|
||||
}
|
||||
|
||||
@@ -154,12 +157,12 @@ int is_symlink(const char *path) {
|
||||
}
|
||||
|
||||
static int mode_verify_socket(mode_t mode) {
|
||||
if (S_ISLNK(mode))
|
||||
return -ELOOP;
|
||||
|
||||
if (S_ISDIR(mode))
|
||||
return -EISDIR;
|
||||
|
||||
if (S_ISLNK(mode))
|
||||
return -ELOOP;
|
||||
|
||||
if (!S_ISSOCK(mode))
|
||||
return -ENOTSOCK;
|
||||
|
||||
@@ -200,15 +203,52 @@ int fd_verify_linked(int fd) {
|
||||
return verify_stat_at(fd, NULL, false, stat_verify_linked, true);
|
||||
}
|
||||
|
||||
int stat_verify_device_node(const struct stat *st) {
|
||||
int stat_verify_block(const struct stat *st) {
|
||||
assert(st);
|
||||
|
||||
if (S_ISDIR(st->st_mode))
|
||||
return -EISDIR;
|
||||
|
||||
if (S_ISLNK(st->st_mode))
|
||||
return -ELOOP;
|
||||
|
||||
if (!S_ISBLK(st->st_mode))
|
||||
return -ENOTBLK;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fd_verify_block(int fd) {
|
||||
if (IN_SET(fd, AT_FDCWD, XAT_FDROOT))
|
||||
return -EISDIR;
|
||||
|
||||
return verify_stat_at(fd, /* path= */ NULL, /* follow= */ false, stat_verify_block, /* verify= */ true);
|
||||
}
|
||||
|
||||
int stat_verify_char(const struct stat *st) {
|
||||
assert(st);
|
||||
|
||||
if (S_ISDIR(st->st_mode))
|
||||
return -EISDIR;
|
||||
|
||||
if (S_ISLNK(st->st_mode))
|
||||
return -ELOOP;
|
||||
|
||||
if (!S_ISCHR(st->st_mode))
|
||||
return -EBADFD;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int stat_verify_device_node(const struct stat *st) {
|
||||
assert(st);
|
||||
|
||||
if (S_ISDIR(st->st_mode))
|
||||
return -EISDIR;
|
||||
|
||||
if (S_ISLNK(st->st_mode))
|
||||
return -ELOOP;
|
||||
|
||||
if (!S_ISBLK(st->st_mode) && !S_ISCHR(st->st_mode))
|
||||
return -ENOTTY;
|
||||
|
||||
@@ -220,6 +260,28 @@ int is_device_node(const char *path) {
|
||||
return verify_stat_at(AT_FDCWD, path, false, stat_verify_device_node, false);
|
||||
}
|
||||
|
||||
int stat_verify_regular_or_block(const struct stat *st) {
|
||||
assert(st);
|
||||
|
||||
if (S_ISDIR(st->st_mode))
|
||||
return -EISDIR;
|
||||
|
||||
if (S_ISLNK(st->st_mode))
|
||||
return -ELOOP;
|
||||
|
||||
if (!S_ISREG(st->st_mode) && !S_ISBLK(st->st_mode))
|
||||
return -EBADFD;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fd_verify_regular_or_block(int fd) {
|
||||
if (IN_SET(fd, AT_FDCWD, XAT_FDROOT))
|
||||
return -EISDIR;
|
||||
|
||||
return verify_stat_at(fd, /* path= */ NULL, /* follow= */ false, stat_verify_regular_or_block, /* verify= */ true);
|
||||
}
|
||||
|
||||
int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
struct dirent *buf;
|
||||
|
||||
@@ -28,9 +28,17 @@ int is_socket(const char *path);
|
||||
int stat_verify_linked(const struct stat *st);
|
||||
int fd_verify_linked(int fd);
|
||||
|
||||
int stat_verify_block(const struct stat *st);
|
||||
int fd_verify_block(int fd);
|
||||
|
||||
int stat_verify_char(const struct stat *st);
|
||||
|
||||
int stat_verify_device_node(const struct stat *st);
|
||||
int is_device_node(const char *path);
|
||||
|
||||
int stat_verify_regular_or_block(const struct stat *st);
|
||||
int fd_verify_regular_or_block(int fd);
|
||||
|
||||
int dir_is_empty_at(int dir_fd, const char *path, bool ignore_hidden_or_backup);
|
||||
static inline int dir_is_empty(const char *path, bool ignore_hidden_or_backup) {
|
||||
return dir_is_empty_at(AT_FDCWD, path, ignore_hidden_or_backup);
|
||||
|
||||
@@ -1861,6 +1861,8 @@ int terminal_set_cursor_position(int fd, unsigned row, unsigned column) {
|
||||
}
|
||||
|
||||
static int terminal_verify_same(int input_fd, int output_fd) {
|
||||
int r;
|
||||
|
||||
assert(input_fd >= 0);
|
||||
assert(output_fd >= 0);
|
||||
|
||||
@@ -1871,15 +1873,17 @@ static int terminal_verify_same(int input_fd, int output_fd) {
|
||||
if (fstat(input_fd, &sti) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISCHR(sti.st_mode)) /* TTYs are character devices */
|
||||
return -ENOTTY;
|
||||
r = stat_verify_char(&sti); /* TTYs are character devices */
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
struct stat sto;
|
||||
if (fstat(output_fd, &sto) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISCHR(sto.st_mode))
|
||||
return -ENOTTY;
|
||||
r = stat_verify_char(&sto);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (sti.st_rdev != sto.st_rdev)
|
||||
return -ENOLINK;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "nulstr-util.h"
|
||||
#include "parse-util.h"
|
||||
#include "path-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
#define PASS_JUMP_OFF 4096
|
||||
@@ -308,8 +309,9 @@ int bpf_devices_allow_list_device(
|
||||
return log_warning_errno(errno, "Couldn't stat device %s: %m", node);
|
||||
}
|
||||
|
||||
if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode))
|
||||
return log_warning_errno(SYNTHETIC_ERRNO(ENODEV), "%s is not a device.", node);
|
||||
r = stat_verify_device_node(&st);
|
||||
if (r < 0)
|
||||
return log_warning_errno(r, "'%s' is not a device node.", node);
|
||||
|
||||
mode = st.st_mode;
|
||||
rdev = (dev_t) st.st_rdev;
|
||||
|
||||
+2
-3
@@ -4519,10 +4519,9 @@ const char* manager_get_confirm_spawn(Manager *m) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!S_ISCHR(st.st_mode)) {
|
||||
r = -ENOTTY;
|
||||
r = stat_verify_char(&st);
|
||||
if (r < 0)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
last_errno = 0;
|
||||
return m->confirm_spawn;
|
||||
|
||||
+4
-4
@@ -28,6 +28,7 @@
|
||||
#include "process-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "special.h"
|
||||
#include "stat-util.h"
|
||||
#include "stdio-util.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
@@ -299,10 +300,9 @@ static int run(int argc, char *argv[]) {
|
||||
if (stat(device, &st) < 0)
|
||||
return log_error_errno(errno, "Failed to stat %s: %m", device);
|
||||
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"%s is not a block device.",
|
||||
device);
|
||||
r = stat_verify_block(&st);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "'%s' is not a block device.", device);
|
||||
|
||||
r = sd_device_new_from_stat_rdev(&dev, &st);
|
||||
if (r < 0)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "main-func.h"
|
||||
#include "parse-util.h"
|
||||
#include "pretty-print.h"
|
||||
#include "stat-util.h"
|
||||
#include "static-destruct.h"
|
||||
|
||||
static HibernateInfo arg_info = {};
|
||||
@@ -165,9 +166,9 @@ static int run(int argc, char *argv[]) {
|
||||
if (stat(arg_info.device, &st) < 0)
|
||||
return log_error_errno(errno, "Failed to stat resume device '%s': %m", arg_info.device);
|
||||
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK),
|
||||
"Resume device '%s' is not a block device.", arg_info.device);
|
||||
r = stat_verify_block(&st);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Resume device '%s' is not a block device.", arg_info.device);
|
||||
|
||||
/* The write shall not return if a resume takes place. */
|
||||
r = write_resume_config(st.st_rdev, arg_info.offset, arg_info.device);
|
||||
|
||||
@@ -3214,8 +3214,9 @@ static int home_get_image_path_seat(Home *h, char **ret) {
|
||||
if (stat(ip, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return -ENOTBLK;
|
||||
r = stat_verify_block(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = sd_device_new_from_stat_rdev(&d, &st);
|
||||
if (r < 0)
|
||||
|
||||
+10
-12
@@ -202,16 +202,14 @@ static int probe_file_system_by_path(const char *path, char **ret_fstype, sd_id1
|
||||
}
|
||||
|
||||
static int block_get_size_by_fd(int fd, uint64_t *ret) {
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ret);
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return -ENOTBLK;
|
||||
r = fd_verify_block(fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return blockdev_get_device_size(fd, ret);
|
||||
}
|
||||
@@ -1250,10 +1248,9 @@ static int open_image_file(
|
||||
|
||||
if (fstat(image_fd, &st) < 0)
|
||||
return log_error_errno(errno, "Failed to fstat() image file: %m");
|
||||
if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))
|
||||
return log_error_errno(
|
||||
S_ISDIR(st.st_mode) ? SYNTHETIC_ERRNO(EISDIR) : SYNTHETIC_ERRNO(EBADFD),
|
||||
"Image file %s is not a regular file or block device.", ip);
|
||||
r = stat_verify_regular_or_block(&st);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Image file '%s' is not a regular file or block device.", ip);
|
||||
|
||||
/* Locking block devices doesn't really make sense, as this might interfere with
|
||||
* udev's workings, and these locks aren't network propagated anyway, hence not what
|
||||
@@ -2276,8 +2273,9 @@ int home_create_luks(
|
||||
if (setup->image_fd < 0)
|
||||
return setup->image_fd;
|
||||
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "Device is not a block device, refusing.");
|
||||
r = stat_verify_block(&st);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Device is not a block device, refusing.");
|
||||
|
||||
if (asprintf(&sysfs, "/sys/dev/block/" DEVNUM_FORMAT_STR "/partition", DEVNUM_FORMAT_VAL(st.st_rdev)) < 0)
|
||||
return log_oom();
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "pretty-print.h"
|
||||
#include "qcow2-util.h"
|
||||
#include "ratelimit.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "terminal-util.h"
|
||||
#include "time-util.h"
|
||||
@@ -309,9 +310,9 @@ static int raw_import_open_disk(RawImport *i) {
|
||||
if (fstat(i->output_fd, &i->output_stat) < 0)
|
||||
return log_error_errno(errno, "Failed to stat() output file: %m");
|
||||
|
||||
if (!S_ISREG(i->output_stat.st_mode) && !S_ISBLK(i->output_stat.st_mode))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADFD),
|
||||
"Target file is not a regular file or block device");
|
||||
r = stat_verify_regular_or_block(&i->output_stat);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Target file is not a regular file or block device.");
|
||||
|
||||
if (i->offset != UINT64_MAX) {
|
||||
if (lseek(i->output_fd, i->offset, SEEK_SET) < 0)
|
||||
|
||||
@@ -2456,7 +2456,6 @@ _public_ int sd_journal_open_files(sd_journal **ret, const char **paths, int fla
|
||||
|
||||
_public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
|
||||
_cleanup_(sd_journal_closep) sd_journal *j = NULL;
|
||||
struct stat st;
|
||||
bool take_fd;
|
||||
int r;
|
||||
|
||||
@@ -2464,11 +2463,9 @@ _public_ int sd_journal_open_directory_fd(sd_journal **ret, int fd, int flags) {
|
||||
assert_return(fd >= 0, -EBADF);
|
||||
assert_return((flags & ~OPEN_DIRECTORY_FD_ALLOWED_FLAGS) == 0, -EINVAL);
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
return -EBADFD;
|
||||
r = fd_verify_directory(fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
take_fd = FLAGS_SET(flags, SD_JOURNAL_TAKE_DIRECTORY_FD);
|
||||
j = journal_new(flags & ~SD_JOURNAL_TAKE_DIRECTORY_FD, NULL, NULL);
|
||||
|
||||
@@ -1413,9 +1413,9 @@ static int discover_device(void) {
|
||||
if (S_ISREG(st.st_mode))
|
||||
return discover_loop_backing_file();
|
||||
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Unsupported mount source type for --discover: %s", arg_mount_what);
|
||||
r = stat_verify_block(&st);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Unsupported mount source type for --discover: %s", arg_mount_what);
|
||||
|
||||
r = sd_device_new_from_stat_rdev(&d, &st);
|
||||
if (r < 0)
|
||||
|
||||
@@ -158,16 +158,10 @@ static int validate_image_fd(int fd, MountImageParameters *p) {
|
||||
assert(fd >= 0);
|
||||
assert(p);
|
||||
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
/* Only support regular files and block devices. Let's use stat_verify_regular() here for the nice
|
||||
* error numbers it generates. */
|
||||
if (!S_ISBLK(st.st_mode)) {
|
||||
r = stat_verify_regular(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
/* Only support regular files and block devices. */
|
||||
r = fd_verify_regular_or_block(fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
fl = fd_verify_safe_flags_full(fd, O_NONBLOCK);
|
||||
if (fl < 0)
|
||||
|
||||
+3
-2
@@ -2049,8 +2049,9 @@ static int copy_devnode_one(const char *dest, const char *node, bool check) {
|
||||
log_debug_errno(errno, "Device node %s does not exist, ignoring.", from);
|
||||
return 0;
|
||||
}
|
||||
if (!S_ISCHR(st.st_mode) && !S_ISBLK(st.st_mode))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ESTALE), "%s is not a device node.", from);
|
||||
r = stat_verify_device_node(&st);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "'%s' is not a device node.", from);
|
||||
|
||||
/* Create the parent directory of the device node. Here, we assume that the path has at most one
|
||||
* subdirectory under /dev/, e.g. /dev/net/tun. */
|
||||
|
||||
+2
-22
@@ -3226,26 +3226,6 @@ static int determine_current_padding(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verify_regular_or_block(int fd) {
|
||||
struct stat st;
|
||||
|
||||
assert(fd >= 0);
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (S_ISDIR(st.st_mode))
|
||||
return -EISDIR;
|
||||
|
||||
if (S_ISLNK(st.st_mode))
|
||||
return -ELOOP;
|
||||
|
||||
if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))
|
||||
return -EBADFD;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int context_copy_from_one(Context *context, const char *src) {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
_cleanup_(fdisk_unref_contextp) struct fdisk_context *c = NULL;
|
||||
@@ -3261,9 +3241,9 @@ static int context_copy_from_one(Context *context, const char *src) {
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = verify_regular_or_block(fd);
|
||||
r = fd_verify_regular_or_block(fd);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "%s is not a file nor a block device: %m", src);
|
||||
return log_error_errno(r, "'%s' is not a file nor a block device: %m", src);
|
||||
|
||||
r = fdisk_new_context_at(fd, /* path= */ NULL, /* read_only= */ true, /* sector_size= */ UINT32_MAX, &c);
|
||||
if (r < 0)
|
||||
|
||||
@@ -149,8 +149,9 @@ int btrfs_get_block_device_at(int dir_fd, const char *path, dev_t *ret) {
|
||||
if (stat((char*) di.path, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return -ENOTBLK;
|
||||
r = stat_verify_block(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (major(st.st_rdev) == 0)
|
||||
return -ENODEV;
|
||||
@@ -878,18 +879,15 @@ static int subvol_remove_children(int fd, const char *subvolume, uint64_t subvol
|
||||
|
||||
struct btrfs_ioctl_vol_args vol_args = {};
|
||||
_cleanup_close_ int subvol_fd = -EBADF;
|
||||
struct stat st;
|
||||
bool made_writable = false;
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(subvolume);
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
return -EINVAL;
|
||||
r = fd_verify_directory(fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
subvol_fd = openat(fd, subvolume, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY|O_NOFOLLOW);
|
||||
if (subvol_fd < 0)
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "fd-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "path-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "strv.h"
|
||||
#include "user-util.h"
|
||||
#include "xattr-util.h"
|
||||
@@ -144,6 +145,7 @@ int fd_chown_recursive(
|
||||
|
||||
int duplicated_fd = -EBADF;
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
/* Note that the slightly different order of fstat() and the checks here and in
|
||||
* path_chown_recursive(). That's because when we open the directory ourselves we can specify
|
||||
@@ -153,8 +155,9 @@ int fd_chown_recursive(
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
return -ENOTDIR;
|
||||
r = stat_verify_directory(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!uid_is_valid(uid) && !gid_is_valid(gid) && FLAGS_SET(mask, 07777))
|
||||
return 0; /* nothing to do */
|
||||
|
||||
@@ -1895,17 +1895,15 @@ int image_read_only(Image *i, bool b, RuntimeScope scope) {
|
||||
|
||||
case IMAGE_BLOCK: {
|
||||
_cleanup_close_ int fd = -EBADF;
|
||||
struct stat st;
|
||||
int state = b;
|
||||
|
||||
fd = open(i->path, O_CLOEXEC|O_RDONLY|O_NONBLOCK|O_NOCTTY);
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return -ENOTTY;
|
||||
r = fd_verify_block(fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (ioctl(fd, BLKROSET, &state) < 0)
|
||||
return -errno;
|
||||
|
||||
@@ -2141,14 +2141,16 @@ DissectedImage* dissected_image_unref(DissectedImage *m) {
|
||||
static int is_loop_device(const char *path) {
|
||||
char s[SYS_BLOCK_PATH_MAX("/../loop/")];
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
if (stat(path, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return -ENOTBLK;
|
||||
r = stat_verify_block(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
xsprintf_sys_block_path(s, "/loop/", st.st_dev);
|
||||
if (access(s, F_OK) < 0) {
|
||||
|
||||
@@ -297,8 +297,9 @@ static int verify_fsroot_dir(
|
||||
(unprivileged_mode && ERRNO_IS_NEG_PRIVILEGE(r)) ? LOG_DEBUG : LOG_ERR, r,
|
||||
"Failed to determine block device node of \"%s\": %m", path);
|
||||
|
||||
if (!S_ISDIR(sx.stx_mode))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "Path \"%s\" is not a directory", path);
|
||||
r = statx_verify_directory(&sx);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Path \"%s\" is not a directory", path);
|
||||
|
||||
if (!FLAGS_SET(sx.stx_attributes, STATX_ATTR_MOUNT_ROOT))
|
||||
return log_full_errno(searching ? LOG_DEBUG : LOG_ERR,
|
||||
@@ -477,8 +478,9 @@ int find_esp_and_warn_at_full(
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return log_error_errno(errno, "Failed to stat '%s': %m", p);
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "ESP path '%s' is not a directory.", p);
|
||||
r = stat_verify_directory(&st);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "ESP path '%s' is not a directory.", p);
|
||||
|
||||
if (ret_path)
|
||||
*ret_path = TAKE_PTR(p);
|
||||
@@ -829,8 +831,9 @@ int find_xbootldr_and_warn_at_full(
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return log_error_errno(errno, "Failed to stat '%s': %m", p);
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTDIR), "XBOOTLDR path '%s' is not a directory.", p);
|
||||
r = stat_verify_directory(&st);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "XBOOTLDR path '%s' is not a directory.", p);
|
||||
|
||||
if (ret_path)
|
||||
*ret_path = TAKE_PTR(p);
|
||||
|
||||
@@ -37,14 +37,16 @@ int read_fiemap(int fd, struct fiemap **ret) {
|
||||
uint32_t result_extents = 0;
|
||||
uint64_t fiemap_start = 0, fiemap_length;
|
||||
const size_t n_extra = DIV_ROUND_UP(sizeof(struct fiemap), sizeof(struct fiemap_extent));
|
||||
int r;
|
||||
|
||||
assert(fd >= 0);
|
||||
assert(ret);
|
||||
|
||||
if (fstat(fd, &statinfo) < 0)
|
||||
return log_debug_errno(errno, "Cannot determine file size: %m");
|
||||
if (!S_ISREG(statinfo.st_mode))
|
||||
return -ENOTTY;
|
||||
r = stat_verify_regular(&statinfo);
|
||||
if (r < 0)
|
||||
return r;
|
||||
fiemap_length = statinfo.st_size;
|
||||
|
||||
/* Zero this out in case we run on a file with no extents */
|
||||
@@ -209,8 +211,9 @@ static int swap_entry_get_resume_config(SwapEntry *swap) {
|
||||
return -errno;
|
||||
|
||||
if (!swap->swapfile) {
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return -ENOTBLK;
|
||||
r = stat_verify_block(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
swap->devno = st.st_rdev;
|
||||
swap->offset = 0;
|
||||
|
||||
+12
-12
@@ -378,9 +378,9 @@ static int loop_configure(
|
||||
}
|
||||
|
||||
static int fd_get_max_discard(int fd, uint64_t *ret) {
|
||||
struct stat st;
|
||||
char sysfs_path[STRLEN("/sys/dev/block/" ":" "/queue/discard_max_bytes") + DECIMAL_STR_MAX(dev_t) * 2 + 1];
|
||||
_cleanup_free_ char *buffer = NULL;
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
assert(ret);
|
||||
@@ -388,8 +388,9 @@ static int fd_get_max_discard(int fd, uint64_t *ret) {
|
||||
if (fstat(ASSERT_FD(fd), &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return -ENOTBLK;
|
||||
r = stat_verify_block(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
xsprintf(sysfs_path, "/sys/dev/block/" DEVNUM_FORMAT_STR "/queue/discard_max_bytes", DEVNUM_FORMAT_VAL(st.st_rdev));
|
||||
|
||||
@@ -401,14 +402,16 @@ static int fd_get_max_discard(int fd, uint64_t *ret) {
|
||||
}
|
||||
|
||||
static int fd_set_max_discard(int fd, uint64_t max_discard) {
|
||||
struct stat st;
|
||||
char sysfs_path[STRLEN("/sys/dev/block/" ":" "/queue/discard_max_bytes") + DECIMAL_STR_MAX(dev_t) * 2 + 1];
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
if (fstat(ASSERT_FD(fd), &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISBLK(st.st_mode))
|
||||
return -ENOTBLK;
|
||||
r = stat_verify_block(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
xsprintf(sysfs_path, "/sys/dev/block/" DEVNUM_FORMAT_STR "/queue/discard_max_bytes", DEVNUM_FORMAT_VAL(st.st_rdev));
|
||||
|
||||
@@ -820,7 +823,6 @@ int loop_device_make_by_path_memory(
|
||||
|
||||
_cleanup_close_ int fd = -EBADF, mfd = -EBADF;
|
||||
_cleanup_free_ char *fn = NULL;
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
@@ -837,11 +839,9 @@ int loop_device_make_by_path_memory(
|
||||
if (fd < 0)
|
||||
return -errno;
|
||||
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
if (!S_ISREG(st.st_mode) && !S_ISBLK(st.st_mode))
|
||||
return -EBADF;
|
||||
r = fd_verify_regular_or_block(fd);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = path_extract_filename(path, &fn);
|
||||
if (r < 0)
|
||||
|
||||
+3
-2
@@ -37,8 +37,9 @@ static int patch_dirfd_mode(
|
||||
|
||||
if (fstat(dfd, &st) < 0)
|
||||
return -errno;
|
||||
if (!S_ISDIR(st.st_mode))
|
||||
return -ENOTDIR;
|
||||
r = stat_verify_directory(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (FLAGS_SET(st.st_mode, 0700)) { /* Already set? */
|
||||
if (refuse_already_set)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "socket-label.h"
|
||||
#include "socket-netlink.h"
|
||||
#include "socket-util.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
|
||||
int socket_address_parse(SocketAddress *a, const char *s) {
|
||||
@@ -497,8 +498,9 @@ int af_unix_get_qlen(int fd, uint32_t *ret) {
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) < 0)
|
||||
return -errno;
|
||||
if (!S_ISSOCK(st.st_mode))
|
||||
return -ENOTSOCK;
|
||||
r = stat_verify_socket(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
_cleanup_(sd_netlink_unrefp) sd_netlink *nl = NULL;
|
||||
r = sd_sock_diag_socket_open(&nl);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "log.h"
|
||||
#include "path-util.h"
|
||||
#include "ratelimit.h"
|
||||
#include "stat-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "time-util.h"
|
||||
@@ -55,6 +56,7 @@ static int saturated_usec_to_sec(usec_t val) {
|
||||
|
||||
static int watchdog_get_sysfs_path(const char *filename, char **ret_path) {
|
||||
struct stat st;
|
||||
int r;
|
||||
|
||||
if (watchdog_fd < 0)
|
||||
return -EBADF;
|
||||
@@ -62,8 +64,9 @@ static int watchdog_get_sysfs_path(const char *filename, char **ret_path) {
|
||||
if (fstat(watchdog_fd, &st))
|
||||
return -errno;
|
||||
|
||||
if (!S_ISCHR(st.st_mode))
|
||||
return -EBADF;
|
||||
r = stat_verify_char(&st);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (asprintf(ret_path, "/sys/dev/char/"DEVNUM_FORMAT_STR"/%s", DEVNUM_FORMAT_VAL(st.st_rdev), filename) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
Reference in New Issue
Block a user