summaryrefslogtreecommitdiff
path: root/util/nvmutil
diff options
context:
space:
mode:
Diffstat (limited to 'util/nvmutil')
-rw-r--r--util/nvmutil/include/common.h6
-rw-r--r--util/nvmutil/lib/file.c182
2 files changed, 125 insertions, 63 deletions
diff --git a/util/nvmutil/include/common.h b/util/nvmutil/include/common.h
index e856664f..6ae7af04 100644
--- a/util/nvmutil/include/common.h
+++ b/util/nvmutil/include/common.h
@@ -324,6 +324,12 @@ size_t conv_argv_part_num(const char *part_str);
*/
void open_gbe_file(void);
+int fd_verify_regular(int fd,
+ const struct stat *expected,
+ struct stat *out);
+int fd_verify_identity(int fd,
+ const struct stat *expected,
+ struct stat *out);
int is_owner(struct stat *st);
int lock_file(int fd, int flags);
int same_file(int fd, struct stat *st_old, int check_size);
diff --git a/util/nvmutil/lib/file.c b/util/nvmutil/lib/file.c
index 50b48065..f3ef15cb 100644
--- a/util/nvmutil/lib/file.c
+++ b/util/nvmutil/lib/file.c
@@ -56,13 +56,8 @@ same_file(int fd, struct stat *st_old,
if (fstat(fd, &st) == -1)
goto err_same_file;
- if (st.st_dev != st_old->st_dev ||
- st.st_ino != st_old->st_ino ||
- !S_ISREG(st.st_mode)) {
-
- errno = ESTALE;
+ if (fd_verify_regular(fd, st_old, &st) < 0)
goto err_same_file;
- }
if (check_size &&
st.st_size != st_old->st_size)
@@ -90,6 +85,17 @@ err_same_file:
make it return, and handle the return value/errno
(this could return e.g. EINTR)
+
+ TODO: this function is not used by mkhtemp, nor will
+ it probably be, it's currently used by nvmutil,
+ for opening intel gbe nvm config files. i can
+ probably remove it though and unify witth some
+ of the verification code now used for mkhtemp
+
+TODO: and don't abort. return -1. and handle in the caller.
+
+minor obstacle: the mkhtemp code always requires absolute
+paths, whereas the gbe editor takes relative paths.
*/
void
xopen(int *fd_ptr, const char *path, int flags, struct stat *st)
@@ -259,15 +265,12 @@ new_tmpfile(int *fd, char **path)
size_t dirlen;
size_t destlen;
- size_t baselen;
char *dest = NULL; /* final path */
int saved_errno = errno;
int dirfd = -1;
const char *fname = NULL;
struct stat st_dir_initial;
- char *dir = NULL;
- char *base = NULL;
if (path == NULL || fd == NULL) {
errno = EFAULT;
@@ -294,6 +297,10 @@ new_tmpfile(int *fd, char **path)
if (slen(tmpdir, maxlen, &dirlen) < 0)
goto err_new_tmpfile;
+ if (*tmpdir == '\0')
+ goto err_new_tmpfile;
+ if (*tmpdir != '/')
+ goto err_new_tmpfile;
/* using sizeof (not slen) adds an extra byte,
* useful because we either want '.' or '/'
@@ -336,10 +343,6 @@ new_tmpfile(int *fd, char **path)
(void) close_on_eintr(dirfd);
dirfd = -1;
}
- if (dir != NULL) {
- free(dir);
- dir = NULL;
- }
errno = saved_errno;
@@ -371,11 +374,6 @@ err_new_tmpfile:
*fd = -1;
}
- if (dir != NULL) {
- free(dir);
- dir = NULL;
- }
-
errno = saved_errno;
return -1;
@@ -694,6 +692,7 @@ mkhtemp(int *fd,
size_t max_len = 4096;
#endif
int r;
+ char *end;
if (fd == NULL ||
template == NULL ||
@@ -736,14 +735,11 @@ mkhtemp(int *fd,
}
/* count trailing X */
- {
- char *end = template + len;
-
- while (end > template && *--end == 'X')
- xc++;
- }
+ end = template + len;
+ while (end > template && *--end == 'X')
+ xc++;
- if (xc < 6 || xc > len) {
+ if (xc < 12 || xc > len) {
errno = EINVAL;
return -1;
}
@@ -784,9 +780,11 @@ mkhtemp(int *fd,
fd,
st);
- /* DoS mitigation; add jitter delay (0–1023 µs) */
- if (r != 1 && retries >= MKHTEMP_SPIN_THRESHOLD)
- usleep((useconds_t)rlong() & 0x3FF);
+ if (r != 1) {
+ if (retries >= MKHTEMP_SPIN_THRESHOLD)
+ usleep((useconds_t)rlong() & 0x3FF);
+ continue;
+ }
/* success: copy final name back */
memcpy(template + len - fname_len,
@@ -825,17 +823,18 @@ mkhtemp_try_create(int dirfd,
struct stat st_open;
int saved_errno = errno;
int close_errno;
+ int rval = -1;
if (mkhtemp_fill_random(p, xc) < 0)
- return -1;
+ goto err;
if (fstat(dirfd, &st_dir_now) < 0)
- return -1;
+ goto err;
if (st_dir_now.st_dev != st_dir_initial->st_dev ||
st_dir_now.st_ino != st_dir_initial->st_ino) {
errno = ESTALE;
- return -1;
+ goto err;
}
*fd = openat2p(dirfd, fname_copy,
@@ -843,40 +842,53 @@ mkhtemp_try_create(int dirfd,
O_NOFOLLOW | O_CLOEXEC | O_NOCTTY,
0600);
- if (*fd >= 0) {
+ if (*fd < 0) {
+ if (errno == EEXIST ||
+ errno == EINTR ||
+ errno == EAGAIN ||
+ errno == EWOULDBLOCK ||
+ errno == ETXTBSY) {
+
+ rval = 0;
+ goto out;
+ }
+ goto err;
+ }
- if (fstat(*fd, &st_open) < 0)
- return -1;
+ /* fd is now live */
- if (fstat(dirfd, &st_dir_now) < 0)
- return -1;
+ if (fstat(*fd, &st_open) < 0)
+ goto err;
- if (st_dir_now.st_dev != st_dir_initial->st_dev ||
- st_dir_now.st_ino != st_dir_initial->st_ino) {
+ if (fstat(dirfd, &st_dir_now) < 0)
+ goto err;
- close_errno = errno;
- (void) close_on_eintr(*fd);
- errno = close_errno;
+ if (st_dir_now.st_dev != st_dir_initial->st_dev ||
+ st_dir_now.st_ino != st_dir_initial->st_ino) {
+ errno = ESTALE;
+ goto err;
+ }
- errno = ESTALE;
- return -1;
- }
+ if (secure_file(fd, st, &st_open,
+ O_APPEND, 1, 1, 0600) < 0)
+ goto err;
- if (secure_file(fd, st, &st_open, O_APPEND, 1, 1, 0600) < 0)
- return -1;
+ errno = saved_errno;
+ rval = 1;
+ goto out;
- errno = saved_errno;
- return 1; /* success */
- }
+err:
+ close_errno = errno;
- if (errno == EEXIST ||
- errno == EINTR ||
- errno == EAGAIN ||
- errno == EWOULDBLOCK ||
- errno == ETXTBSY)
- return 0; /* retry */
+ if (fd != NULL && *fd >= 0) {
+ (void) close_on_eintr(*fd);
+ *fd = -1;
+ }
- return -1; /* fatal */
+ errno = close_errno;
+ rval = -1;
+out:
+ return rval;
}
int
@@ -985,21 +997,17 @@ int secure_file(int *fd,
}
}
- if (fstat(*fd, st) == -1)
+ if (fstat(*fd, &st_now) == -1)
goto err_secure_file;
- /* verify inode/device stability */
if (expected != NULL) {
-
if (st_now.st_dev != expected->st_dev ||
- st_now.st_ino != expected->st_ino) {
-
+ st_now.st_ino != expected->st_ino) {
errno = ESTALE;
goto err_secure_file;
}
}
- /* now copy to caller */
*st = st_now;
if (!S_ISREG(st->st_mode)) {
@@ -1007,6 +1015,9 @@ int secure_file(int *fd,
goto err_secure_file;
}
+ if (fd_verify_regular(*fd, expected, st) < 0)
+ goto err_secure_file;
+
if (check_seek) {
/* check if it's seekable */
@@ -1058,6 +1069,51 @@ err_secure_file:
}
int
+fd_verify_regular(int fd,
+ const struct stat *expected,
+ struct stat *out)
+{
+ if (fd_verify_identity(fd, expected, out) < 0)
+ return -1;
+
+ if (!S_ISREG(out->st_mode)) {
+ errno = EBADF;
+ return -1;
+ }
+
+ return 0; /* regular file */
+}
+
+int
+fd_verify_identity(int fd,
+ const struct stat *expected,
+ struct stat *out)
+{
+ struct stat st_now;
+ int saved_errno = errno;
+
+ if (fd < 0 || expected == NULL) {
+ errno = EFAULT;
+ return -1;
+ }
+
+ if (fstat(fd, &st_now) < 0)
+ return -1;
+
+ if (st_now.st_dev != expected->st_dev ||
+ st_now.st_ino != expected->st_ino) {
+ errno = ESTALE;
+ return -1;
+ }
+
+ if (out != NULL)
+ *out = st_now;
+
+ errno = saved_errno;
+ return 0;
+}
+
+int
is_owner(struct stat *st)
{
if (st == NULL) {
@@ -1812,7 +1868,7 @@ fs_open(const char *path, int flags)
}
fs = rootfs();
- if (!fs)
+ if (fs == NULL)
return -1;
rel = path + 1;