On Mon, Dec 18, 2023 at 11:57 PM Vinicius Costa Gomes <vinicius.gomes@xxxxxxxxx> wrote: > > Christian Brauner <brauner@xxxxxxxxxx> writes: > > >> > Yes, the important thing is that an object cannot change > >> > its non_refcount property during its lifetime - > >> > >> ... which means that put_creds_ref() should assert that > >> there is only a single refcount - the one handed out by > >> prepare_creds_ref() before removing non_refcount or > >> directly freeing the cred object. > >> > >> I must say that the semantics of making a non-refcounted copy > >> to an object whose lifetime is managed by the caller sounds a lot > >> less confusing to me. > > > > So can't we do an override_creds() variant that is effectively just: Yes, I think that we can.... > > > > /* caller guarantees lifetime of @new */ > > const struct cred *foo_override_cred(const struct cred *new) > > { > > const struct cred *old = current->cred; > > rcu_assign_pointer(current->cred, new); > > return old; > > } > > > > /* caller guarantees lifetime of @old */ > > void foo_revert_creds(const struct cred *old) > > { > > const struct cred *override = current->cred; > > rcu_assign_pointer(current->cred, old); > > } > > Even better(?), we can do this in the actual guard helpers to discourage use without a guard: struct override_cred { struct cred *cred; }; DEFINE_GUARD(override_cred, struct override_cred *, override_cred_save(_T), override_cred_restore(_T)); ... void override_cred_save(struct override_cred *new) { new->cred = rcu_replace_pointer(current->cred, new->cred, true); } void override_cred_restore(struct override_cred *old) { rcu_assign_pointer(current->cred, old->cred); } > > Maybe I really fail to understand this problem or the proposed solution: > > the single reference that overlayfs keeps in ovl->creator_cred is tied > > to the lifetime of the overlayfs superblock, no? And anyone who needs a > > long term cred reference e.g, file->f_cred will take it's own reference > > anyway. So it should be safe to just keep that reference alive until > > overlayfs is unmounted, no? I'm sure it's something quite obvious why > > that doesn't work but I'm just not seeing it currently. > > My read of the code says that what you are proposing should work. (what > I am seeing is that in the "optimized" cases, the only practical effect > of override/revert is the rcu_assign_pointer() dance) > > I guess that the question becomes: Do we want this property (that the > 'cred' associated with a subperblock/similar is long lived and the > "inner" refcount can be omitted) to be encoded in the constructor? Or do > we want it to be "encoded" in a call by call basis? > Neither. Christian's proposal does not involve marking the cred object as long lived, which looks a much better idea to me. The performance issues you observed are (probably) due to get/put of cred refcount in the helpers {override,revert}_creds(). Christian suggested lightweight variants of {override,revert}_creds() that do not change refcount. Combining those with a guard and I don't see what can go wrong (TM). If you try this out and post a patch, please be sure to include the motivation for the patch along with performance numbers in the commit message, even if only posting an RFC patch. Thanks, Amir.