"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "lib/utils_device_locking.c" between
cryptsetup-2.0.6.tar.xz and cryptsetup-2.1.0.tar.xz

About: cryptsetup is a utility used to conveniently setup disk encryption based on the dm-crypt kernel module. These include plain dm-crypt volumes, LUKS volumes, loop-AES and TrueCrypt compatible format.

utils_device_locking.c  (cryptsetup-2.0.6.tar.xz):utils_device_locking.c  (cryptsetup-2.1.0.tar.xz)
/* /*
* Metadata on-disk locking for processes serialization * Metadata on-disk locking for processes serialization
* *
* Copyright (C) 2016-2018, Red Hat, Inc. All rights reserved. * Copyright (C) 2016-2019 Red Hat, Inc. All rights reserved.
* Copyright (C) 2016-2018, Ondrej Kozina. All rights reserved. * Copyright (C) 2016-2019 Ondrej Kozina
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 * as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version. * of the License, or (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * GNU General Public License for more details.
skipping to change at line 78 skipping to change at line 78
return (r < 0 || (size_t)r >= res_size) ? -EINVAL : 0; return (r < 0 || (size_t)r >= res_size) ? -EINVAL : 0;
} }
static int open_lock_dir(struct crypt_device *cd, const char *dir, const char *b ase) static int open_lock_dir(struct crypt_device *cd, const char *dir, const char *b ase)
{ {
int dirfd, lockdfd; int dirfd, lockdfd;
dirfd = open(dir, O_RDONLY | O_DIRECTORY | O_CLOEXEC); dirfd = open(dir, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
if (dirfd < 0) { if (dirfd < 0) {
log_dbg("Failed to open directory %s: (%d: %s).", dir, errno, str error(errno)); log_dbg(cd, "Failed to open directory %s: (%d: %s).", dir, errno, strerror(errno));
if (errno == ENOTDIR || errno == ENOENT) if (errno == ENOTDIR || errno == ENOENT)
log_err(cd, _("Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."), dir, base); log_err(cd, _("Locking aborted. The locking path %s/%s is unusable (not a directory or missing)."), dir, base);
return -EINVAL; return -EINVAL;
} }
lockdfd = openat(dirfd, base, O_RDONLY | O_NOFOLLOW | O_DIRECTORY | O_CLO EXEC); lockdfd = openat(dirfd, base, O_RDONLY | O_NOFOLLOW | O_DIRECTORY | O_CLO EXEC);
if (lockdfd < 0) { if (lockdfd < 0) {
if (errno == ENOENT) { if (errno == ENOENT) {
log_std(cd, _("WARNING: Locking directory %s/%s is missin g!\n"), dir, base); log_std(cd, _("WARNING: Locking directory %s/%s is missin g!\n"), dir, base);
/* success or failure w/ errno == EEXIST either way just try to open the 'base' directory again */ /* success or failure w/ errno == EEXIST either way just try to open the 'base' directory again */
if (mkdirat(dirfd, base, DEFAULT_LUKS2_LOCK_DIR_PERMS) && errno != EEXIST) if (mkdirat(dirfd, base, DEFAULT_LUKS2_LOCK_DIR_PERMS) && errno != EEXIST)
log_dbg("Failed to create directory %s in %s (%d: %s).", base, dir, errno, strerror(errno)); log_dbg(cd, "Failed to create directory %s in %s (%d: %s).", base, dir, errno, strerror(errno));
else else
lockdfd = openat(dirfd, base, O_RDONLY | O_NOFOLL OW | O_DIRECTORY | O_CLOEXEC); lockdfd = openat(dirfd, base, O_RDONLY | O_NOFOLL OW | O_DIRECTORY | O_CLOEXEC);
} else { } else {
log_dbg("Failed to open directory %s/%s: (%d: %s)", dir, base, errno, strerror(errno)); log_dbg(cd, "Failed to open directory %s/%s: (%d: %s)", d ir, base, errno, strerror(errno));
if (errno == ENOTDIR || errno == ELOOP) if (errno == ENOTDIR || errno == ELOOP)
log_err(cd, _("Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."), dir, base, base); log_err(cd, _("Locking aborted. The locking path %s/%s is unusable (%s is not a directory)."), dir, base, base);
} }
} }
close(dirfd); close(dirfd);
return lockdfd >= 0 ? lockdfd : -EINVAL; return lockdfd >= 0 ? lockdfd : -EINVAL;
} }
static int open_resource(struct crypt_device *cd, const char *res) static int open_resource(struct crypt_device *cd, const char *res)
{ {
int err, lockdir_fd, r; int err, lockdir_fd, r;
char dir[] = DEFAULT_LUKS2_LOCK_PATH, char dir[] = DEFAULT_LUKS2_LOCK_PATH,
base[] = DEFAULT_LUKS2_LOCK_PATH; base[] = DEFAULT_LUKS2_LOCK_PATH;
lockdir_fd = open_lock_dir(cd, dirname(dir), basename(base)); lockdir_fd = open_lock_dir(cd, dirname(dir), basename(base));
if (lockdir_fd < 0) if (lockdir_fd < 0)
return -EINVAL; return -EINVAL;
log_dbg("Opening lock resource file %s/%s", DEFAULT_LUKS2_LOCK_PATH, res) ; log_dbg(cd, "Opening lock resource file %s/%s", DEFAULT_LUKS2_LOCK_PATH, res);
r = openat(lockdir_fd, res, O_CREAT | O_NOFOLLOW | O_RDWR | O_CLOEXEC, 07 77); r = openat(lockdir_fd, res, O_CREAT | O_NOFOLLOW | O_RDWR | O_CLOEXEC, 07 77);
err = errno; err = errno;
close(lockdir_fd); close(lockdir_fd);
return r < 0 ? -err : r; return r < 0 ? -err : r;
} }
static int acquire_lock_handle(struct crypt_device *cd, const char *device_path, struct crypt_lock_handle *h) static int acquire_lock_handle(struct crypt_device *cd, const char *device_path, struct crypt_lock_handle *h)
{ {
skipping to change at line 172 skipping to change at line 172
/* Wrong device type */ /* Wrong device type */
close(dev_fd); close(dev_fd);
return -EINVAL; return -EINVAL;
} }
h->mode = st.st_mode; h->mode = st.st_mode;
return 0; return 0;
} }
static void release_lock_handle(struct crypt_lock_handle *h) static void release_lock_handle(struct crypt_device *cd, struct crypt_lock_handl e *h)
{ {
char res[PATH_MAX]; char res[PATH_MAX];
struct stat buf_a, buf_b; struct stat buf_a, buf_b;
if (S_ISBLK(h->mode) && /* was it block device */ if (S_ISBLK(h->mode) && /* was it block device */
!flock(h->flock_fd, LOCK_EX | LOCK_NB) && /* lock to drop the file */ !flock(h->flock_fd, LOCK_EX | LOCK_NB) && /* lock to drop the file */
!resource_by_devno(res, sizeof(res), h->devno, 1) && /* acquire lock resource name */ !resource_by_devno(res, sizeof(res), h->devno, 1) && /* acquire lock resource name */
!fstat(h->flock_fd, &buf_a) && /* read inode id referred by fd */ !fstat(h->flock_fd, &buf_a) && /* read inode id referred by fd */
!stat(res, &buf_b) && /* does path file still exist? */ !stat(res, &buf_b) && /* does path file still exist? */
same_inode(buf_a, buf_b)) { /* is it same id as the one referenced by fd? */ same_inode(buf_a, buf_b)) { /* is it same id as the one referenced by fd? */
/* coverity[toctou] */ /* coverity[toctou] */
if (unlink(res)) /* yes? unlink the file */ if (unlink(res)) /* yes? unlink the file */
log_dbg("Failed to unlink resource file: %s", res); log_dbg(cd, "Failed to unlink resource file: %s", res);
} }
if (close(h->flock_fd)) if (close(h->flock_fd))
log_dbg("Failed to close resource fd (%d).", h->flock_fd); log_dbg(cd, "Failed to close resource fd (%d).", h->flock_fd);
} }
int device_locked(struct crypt_lock_handle *h) int device_locked(struct crypt_lock_handle *h)
{ {
return (h && (h->type == DEV_LOCK_READ || h->type == DEV_LOCK_WRITE)); return (h && (h->type == DEV_LOCK_READ || h->type == DEV_LOCK_WRITE));
} }
int device_locked_readonly(struct crypt_lock_handle *h) int device_locked_readonly(struct crypt_lock_handle *h)
{ {
return (h && h->type == DEV_LOCK_READ); return (h && h->type == DEV_LOCK_READ);
skipping to change at line 233 skipping to change at line 233
struct crypt_lock_handle *h = malloc(sizeof(*h)); struct crypt_lock_handle *h = malloc(sizeof(*h));
if (!h) if (!h)
return NULL; return NULL;
do { do {
r = acquire_lock_handle(cd, device_path, h); r = acquire_lock_handle(cd, device_path, h);
if (r) if (r)
break; break;
log_dbg("Acquiring read lock for device %s.", device_path); log_dbg(cd, "Acquiring read lock for device %s.", device_path);
if (flock(h->flock_fd, LOCK_SH)) { if (flock(h->flock_fd, LOCK_SH)) {
log_dbg("Shared flock failed with errno %d.", errno); log_dbg(cd, "Shared flock failed with errno %d.", errno);
r = -EINVAL; r = -EINVAL;
release_lock_handle(h); release_lock_handle(cd, h);
break; break;
} }
log_dbg("Verifying read lock handle for device %s.", device_path) ; log_dbg(cd, "Verifying read lock handle for device %s.", device_p ath);
/* /*
* check whether another libcryptsetup process removed resource f ile before this * check whether another libcryptsetup process removed resource f ile before this
* one managed to flock() it. See release_lock_handle() for detai ls * one managed to flock() it. See release_lock_handle() for detai ls
*/ */
r = verify_lock_handle(device_path, h); r = verify_lock_handle(device_path, h);
if (r) { if (r) {
flock(h->flock_fd, LOCK_UN); flock(h->flock_fd, LOCK_UN);
release_lock_handle(h); release_lock_handle(cd, h);
log_dbg("Read lock handle verification failed."); log_dbg(cd, "Read lock handle verification failed.");
} }
} while (r == -EAGAIN); } while (r == -EAGAIN);
if (r) { if (r) {
free(h); free(h);
return NULL; return NULL;
} }
h->type = DEV_LOCK_READ; h->type = DEV_LOCK_READ;
skipping to change at line 279 skipping to change at line 279
struct crypt_lock_handle *h = malloc(sizeof(*h)); struct crypt_lock_handle *h = malloc(sizeof(*h));
if (!h) if (!h)
return NULL; return NULL;
do { do {
r = acquire_lock_handle(cd, device_path, h); r = acquire_lock_handle(cd, device_path, h);
if (r) if (r)
break; break;
log_dbg("Acquiring write lock for device %s.", device_path); log_dbg(cd, "Acquiring write lock for device %s.", device_path);
if (flock(h->flock_fd, LOCK_EX)) { if (flock(h->flock_fd, LOCK_EX)) {
log_dbg("Exclusive flock failed with errno %d.", errno); log_dbg(cd, "Exclusive flock failed with errno %d.", errn o);
r = -EINVAL; r = -EINVAL;
release_lock_handle(h); release_lock_handle(cd, h);
break; break;
} }
log_dbg("Verifying write lock handle for device %s.", device_path ); log_dbg(cd, "Verifying write lock handle for device %s.", device_ path);
/* /*
* check whether another libcryptsetup process removed resource f ile before this * check whether another libcryptsetup process removed resource f ile before this
* one managed to flock() it. See release_lock_handle() for detai ls * one managed to flock() it. See release_lock_handle() for detai ls
*/ */
r = verify_lock_handle(device_path, h); r = verify_lock_handle(device_path, h);
if (r) { if (r) {
flock(h->flock_fd, LOCK_UN); flock(h->flock_fd, LOCK_UN);
release_lock_handle(h); release_lock_handle(cd, h);
log_dbg("Write lock handle verification failed."); log_dbg(cd, "Write lock handle verification failed.");
} }
} while (r == -EAGAIN); } while (r == -EAGAIN);
if (r) { if (r) {
free(h); free(h);
return NULL; return NULL;
} }
h->type = DEV_LOCK_WRITE; h->type = DEV_LOCK_WRITE;
return h; return h;
} }
void device_unlock_handle(struct crypt_lock_handle *h) void device_unlock_handle(struct crypt_device *cd, struct crypt_lock_handle *h)
{ {
if (flock(h->flock_fd, LOCK_UN)) if (flock(h->flock_fd, LOCK_UN))
log_dbg("flock on fd %d failed.", h->flock_fd); log_dbg(cd, "flock on fd %d failed.", h->flock_fd);
release_lock_handle(h); release_lock_handle(cd, h);
free(h); free(h);
} }
int device_locked_verify(int dev_fd, struct crypt_lock_handle *h) int device_locked_verify(struct crypt_device *cd, int dev_fd, struct crypt_lock_ handle *h)
{ {
char res[PATH_MAX]; char res[PATH_MAX];
struct stat dev_st, lck_st, st; struct stat dev_st, lck_st, st;
if (fstat(dev_fd, &dev_st) || fstat(h->flock_fd, &lck_st)) if (fstat(dev_fd, &dev_st) || fstat(h->flock_fd, &lck_st))
return 1; return 1;
/* if device handle is regular file the handle must match the lock handle */ /* if device handle is regular file the handle must match the lock handle */
if (S_ISREG(dev_st.st_mode)) { if (S_ISREG(dev_st.st_mode)) {
log_dbg("Veryfing locked device handle (regular file)"); log_dbg(cd, "Veryfing locked device handle (regular file)");
if (!same_inode(dev_st, lck_st)) if (!same_inode(dev_st, lck_st))
return 1; return 1;
} else if (S_ISBLK(dev_st.st_mode)) { } else if (S_ISBLK(dev_st.st_mode)) {
log_dbg("Veryfing locked device handle (bdev)"); log_dbg(cd, "Veryfing locked device handle (bdev)");
if (resource_by_devno(res, sizeof(res), dev_st.st_rdev, 1) || if (resource_by_devno(res, sizeof(res), dev_st.st_rdev, 1) ||
stat(res, &st) || stat(res, &st) ||
!same_inode(lck_st, st)) !same_inode(lck_st, st))
return 1; return 1;
} else } else
return 1; return 1;
return 0; return 0;
} }
 End of changes. 24 change blocks. 
27 lines changed or deleted 27 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)