UPSTREAM: ANDROID: bpf-fuse: Fix Setattr

Setattr implementation was mixing up some flags, and missing some of
them.

Test: atest android.appsecurity.cts.ExternalStorageHostTest
Bug: 202785178
Signed-off-by: Daniel Rosenberg <drosen@google.com>
Change-Id: Id41fa30881766faad5858b658f5b6871c0ae46b3
This commit is contained in:
Daniel Rosenberg 2022-01-14 21:33:59 -08:00 • committed by Alexander Martinz
commit 0f65460b10
No known key found for this signature in database
GPG key ID: CF15BDD9A321A9B2

View file

@ -1644,37 +1644,40 @@ void *fuse_getattr_finalize(struct fuse_args *fa,
return ERR_PTR(err);
}
static void fattr_to_iattr(const struct fuse_setattr_in *arg,
static void fattr_to_iattr(struct fuse_conn *fc,
const struct fuse_setattr_in *arg,
struct iattr *iattr)
{
unsigned int ivalid = arg->valid;
unsigned int fvalid = arg->valid;
if (ivalid & ATTR_MODE)
iattr->ia_valid |= FATTR_MODE, iattr->ia_mode = arg->mode;
if (ivalid & ATTR_UID) {
iattr->ia_valid |= FATTR_UID;
iattr->ia_uid = KUIDT_INIT(arg->uid);
if (fvalid & FATTR_MODE)
iattr->ia_valid |= ATTR_MODE, iattr->ia_mode = arg->mode;
if (fvalid & FATTR_UID) {
iattr->ia_valid |= ATTR_UID;
iattr->ia_uid = make_kuid(fc->user_ns, arg->uid);
}
if (ivalid & ATTR_GID) {
iattr->ia_valid |= FATTR_GID;
iattr->ia_gid = KGIDT_INIT(arg->gid);
if (fvalid & FATTR_GID) {
iattr->ia_valid |= ATTR_GID;
iattr->ia_gid = make_kgid(fc->user_ns, arg->gid);
}
if (ivalid & ATTR_SIZE)
iattr->ia_valid |= FATTR_SIZE, iattr->ia_size = arg->size;
if (ivalid & ATTR_ATIME) {
iattr->ia_valid |= FATTR_ATIME;
if (fvalid & FATTR_SIZE)
iattr->ia_valid |= ATTR_SIZE, iattr->ia_size = arg->size;
if (fvalid & FATTR_ATIME) {
iattr->ia_valid |= ATTR_ATIME;
iattr->ia_atime.tv_sec = arg->atime;
iattr->ia_atime.tv_nsec = arg->atimensec;
if (!(ivalid & ATTR_ATIME_SET))
iattr->ia_valid |= FATTR_ATIME_NOW;
if (!(fvalid & FATTR_ATIME_NOW))
iattr->ia_valid |= ATTR_ATIME_SET;
}
if (ivalid & ATTR_MTIME) {
iattr->ia_valid |= FATTR_MTIME;
if (fvalid & FATTR_MTIME) {
iattr->ia_valid |= ATTR_MTIME;
iattr->ia_mtime.tv_sec = arg->mtime;
iattr->ia_mtime.tv_nsec = arg->mtimensec;
if (!(fvalid & FATTR_MTIME_NOW))
iattr->ia_valid |= ATTR_MTIME_SET;
}
if (ivalid & ATTR_CTIME) {
iattr->ia_valid |= FATTR_CTIME;
if (fvalid & FATTR_CTIME) {
iattr->ia_valid |= ATTR_CTIME;
iattr->ia_ctime.tv_sec = arg->ctime;
iattr->ia_ctime.tv_nsec = arg->ctimensec;
}
@ -1705,12 +1708,21 @@ int fuse_setattr_initialize(struct fuse_args *fa, struct fuse_setattr_io *fsio,
int fuse_setattr_backing(struct fuse_args *fa,
struct dentry *dentry, struct iattr *attr, struct file *file)
{
struct fuse_conn *fc = get_fuse_conn(dentry->d_inode);
const struct fuse_setattr_in *fsi = fa->in_args[0].value;
struct iattr new_attr = {0};
struct path *backing_path = &get_fuse_dentry(dentry)->backing_path;
int res;
fattr_to_iattr(fsi, &new_attr);
fattr_to_iattr(fc, fsi, &new_attr);
/* TODO: Some info doesn't get saved by the attr->fattr->attr transition
* When we actually allow the bpf to change these, we may have to consider
* the extra flags more, or pass more info into the bpf. Until then we can
* keep everything except for ATTR_FILE, since we'd need a file on the
* lower fs. For what it's worth, neither f2fs nor ext4 make use of that
* even if it is present.
*/
new_attr.ia_valid = attr->ia_valid & ~ATTR_FILE;
inode_lock(d_inode(backing_path->dentry));
res = notify_change(backing_path->dentry, &new_attr, NULL);
inode_unlock(d_inode(backing_path->dentry));