-
Notifications
You must be signed in to change notification settings - Fork 305
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Repository locking 🔒 #1292
base: main
Are you sure you want to change the base?
Repository locking 🔒 #1292
Changes from all commits
e297478
07b17fb
50bfa38
bb6ab8e
7be3051
d98bc52
19a4dbf
d613ae6
e9b586e
5321998
0ab32a4
fec6b1f
eba8a17
23b7aa4
4b8d03e
2567a01
39a7211
1c87dfb
c2e091a
615b949
cf2824a
1ccd3db
d31b39e
e3a8476
7c14891
e415247
7ff4b93
8c9f518
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Spurious blank line. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whoops... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will address after #1343. |
||
/* | ||
* Copyright (C) 2014 Colin Walters <[email protected]> | ||
* | ||
|
@@ -35,7 +36,7 @@ impl_ostree_generate_grub2_config (OstreeSysroot *sysroot, int bootversion, int | |
} | ||
|
||
/** | ||
* ostree_cmdprivate: (skip) | ||
* ostree_cmd__private__: (skip) | ||
* | ||
* Do not call this function; it is used to share private API between | ||
* the OSTree commandline and the library. | ||
|
@@ -48,7 +49,14 @@ ostree_cmd__private__ (void) | |
impl_ostree_generate_grub2_config, | ||
_ostree_repo_static_delta_dump, | ||
_ostree_repo_static_delta_query_exists, | ||
_ostree_repo_static_delta_delete | ||
_ostree_repo_static_delta_delete, | ||
/* Remove this when ostree_repo_set_lock_timeout is no longer experimental */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe add a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will address after #1343. |
||
ostree_repo_set_lock_timeout, | ||
/* Remove these when ostree_repo_auto_lock_push and | ||
* ostree_repo_auto_lock_cleanup are no longer experimental | ||
*/ | ||
ostree_repo_auto_lock_push, | ||
ostree_repo_auto_lock_cleanup, | ||
}; | ||
|
||
return &table; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,17 +20,34 @@ | |
#pragma once | ||
|
||
#include "ostree-types.h" | ||
/* This is only needed to get the OstreeRepoLockType and OstreeRepoAutoLock | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe add a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will address after #1343. |
||
* types. This should be removed once they're no longer experimental. | ||
*/ | ||
#include "ostree-repo-private.h" | ||
|
||
G_BEGIN_DECLS | ||
|
||
gboolean _ostree_impl_system_generator (const char *ostree_cmdline, const char *normal_dir, const char *early_dir, const char *late_dir, GError **error); | ||
|
||
/** | ||
* OstreeCmdPrivateVTable: (skip) | ||
* | ||
* Function table to share private API between the OSTree commandline and the | ||
* library. Don't use this. | ||
*/ | ||
typedef struct { | ||
gboolean (* ostree_system_generator) (const char *ostree_cmdline, const char *normal_dir, const char *early_dir, const char *late_dir, GError **error); | ||
gboolean (* ostree_generate_grub2_config) (OstreeSysroot *sysroot, int bootversion, int target_fd, GCancellable *cancellable, GError **error); | ||
gboolean (* ostree_static_delta_dump) (OstreeRepo *repo, const char *delta_id, GCancellable *cancellable, GError **error); | ||
gboolean (* ostree_static_delta_query_exists) (OstreeRepo *repo, const char *delta_id, gboolean *out_exists, GCancellable *cancellable, GError **error); | ||
gboolean (* ostree_static_delta_delete) (OstreeRepo *repo, const char *delta_id, GCancellable *cancellable, GError **error); | ||
/* Remove this when ostree_repo_set_lock_timeout is no longer experimental */ | ||
gboolean (* ostree_repo_set_lock_timeout) (OstreeRepo *repo, gint timeout); | ||
/* Remove these when ostree_repo_auto_lock_push and | ||
* ostree_repo_auto_lock_cleanup are no longer experimental | ||
*/ | ||
OstreeRepoAutoLock * (* ostree_repo_auto_lock_push) (OstreeRepo *repo, OstreeRepoLockType lock_type, GCancellable *cancellable, GError **error); | ||
void (* ostree_repo_auto_lock_cleanup) (OstreeRepoAutoLock *lock); | ||
} OstreeCmdPrivateVTable; | ||
|
||
/* Note this not really "public", we just export the symbol, but not the header */ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,7 @@ | |
#include "ostree-sepolicy-private.h" | ||
#include "ostree-core-private.h" | ||
#include "ostree-repo-private.h" | ||
#include "ostree-autocleanups.h" | ||
|
||
#define WHITEOUT_PREFIX ".wh." | ||
|
||
|
@@ -991,6 +992,16 @@ checkout_tree_at (OstreeRepo *self, | |
g_assert (options->force_copy); | ||
} | ||
|
||
/* Take a shared repo lock to try to ensure objects aren't deleted. If the | ||
* repo is not writable, this will be a noop and we just hope for the | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the repo is not writeable can we really expect objects to be deleted? Are you thinking of the situation where a repo is being operated on by processes belonging to two users: the user deleting objects has write permissions on the repository, and the user reading it does not? We could perhaps fix this by sticking an inotify on the lock file if we only have read-only access to the repository, and bailing out if an exclusive lock is taken on the repository while we’re in a locked section. That might be overengineering things though. It would, however, be a general solution which could be implemented in the generic locking code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The case is simply an unprivileged user trying to checkout from /ostree/repo or /var/lib/flatpak/repo or something like that. They should be allowed to do a checkout as they were before. Like you say, if the repo is not writable by the current user, then they're not going to be deleting any objects. But if, say, flatpak is pruning /var/lib/flatpak/repo while you're trying to do a checkout, bad things could happen. But that's already the case, and I don't think we should optimize for unprivileged users. I'm really just trying to make sure that multiple processes running as the repo owner can't screw each other since that's by far the common case. Since the unprivileged user won't even be able to open the lock file (it's opened 600 particularly so that only repo owners can take exclusive locks), then I don't think they'll be able to get the lock state. An inotify watch is interesting. I'm not sure inotify can tell you when the lock state changes, though, only if it's been opened. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, having done a bit of reading, I don’t think it’s possible to monitor the status of a file lock using inotify. The only way of doing it is to poll with The other approach I can think of is to use a world-writeable directory (somewhere in That said, allowing an unprivileged process to take a lock on a repository it can’t write to allows priority inversion attacks, since there’s no realistic way to stop it taking an exclusive lock. Unless we put shared locks in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I still believe the way this was written where only the repo owner can manage the lock is correct. I think any attempt to allow non-owners to take a lock would be very complex and likely mean that flock-type locking can't be used. |
||
* best... | ||
*/ | ||
g_autoptr(OstreeRepoAutoLock) lock = NULL; | ||
lock = ostree_repo_auto_lock_push (self, OSTREE_REPO_LOCK_SHARED, | ||
cancellable, error); | ||
if (!lock) | ||
return FALSE; | ||
|
||
/* Special case handling for subpath of a non-directory */ | ||
if (g_file_info_get_file_type (source_info) != G_FILE_TYPE_DIRECTORY) | ||
{ | ||
|
@@ -1062,6 +1073,8 @@ canonicalize_options (OstreeRepo *self, | |
* physical filesystem. @source may be any subdirectory of a given | ||
* commit. The @mode and @overwrite_mode allow control over how the | ||
* files are checked out. | ||
* | ||
* This function takes a shared lock on the @self repository. | ||
*/ | ||
gboolean | ||
ostree_repo_checkout_tree (OstreeRepo *self, | ||
|
@@ -1105,6 +1118,8 @@ ostree_repo_checkout_tree (OstreeRepo *self, | |
* default is not to use the repository-internal uncompressed objects | ||
* cache. | ||
* | ||
* This function takes a shared lock on the @self repository. | ||
* | ||
* This function is deprecated. Use ostree_repo_checkout_at() instead. | ||
*/ | ||
gboolean | ||
|
@@ -1150,6 +1165,8 @@ ostree_repo_checkout_tree_at (OstreeRepo *self, | |
* Note in addition that unlike ostree_repo_checkout_tree(), the | ||
* default is not to use the repository-internal uncompressed objects | ||
* cache. | ||
* | ||
* This function takes a shared lock on the @self repository. | ||
*/ | ||
gboolean | ||
ostree_repo_checkout_at (OstreeRepo *self, | ||
|
@@ -1273,12 +1290,21 @@ ostree_repo_devino_cache_new (void) | |
* Call this after finishing a succession of checkout operations; it | ||
* will delete any currently-unused uncompressed objects from the | ||
* cache. | ||
* | ||
* This function takes an exclusive lock on the @self repository. | ||
*/ | ||
gboolean | ||
ostree_repo_checkout_gc (OstreeRepo *self, | ||
GCancellable *cancellable, | ||
GError **error) | ||
{ | ||
/* Take an exclusive repo lock while deleting uncompressed objects */ | ||
g_autoptr(OstreeRepoAutoLock) lock = NULL; | ||
lock = ostree_repo_auto_lock_push (self, OSTREE_REPO_LOCK_EXCLUSIVE, | ||
cancellable, error); | ||
if (!lock) | ||
return FALSE; | ||
|
||
g_autoptr(GHashTable) to_clean_dirs = NULL; | ||
|
||
g_mutex_lock (&self->cache_lock); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should just be able to pass
config.h
toOSTree_1_0_gir_FILES
and it will be#include
d into the temporary C file whichg-ir-scanner
generates as part of the scanning process.I think order is preserved, so list it first in
OSTree_1_0_gir_FILES
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting, I didn't know that. I'll try that locally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was separately fixed in #1322.