On 8/18/20 3:27 AM, Martin KaFai Lau wrote: > On Mon, Aug 03, 2020 at 06:46:53PM +0200, KP Singh wrote: >> From: KP Singh <kpsingh@xxxxxxxxxx> >> >> Similar to bpf_local_storage for sockets, add local storage for inodes. >> The life-cycle of storage is managed with the life-cycle of the inode. >> i.e. the storage is destroyed along with the owning inode. >> >> The BPF LSM allocates an __rcu pointer to the bpf_local_storage in the >> security blob which are now stackable and can co-exist with other LSMs. >> >> Signed-off-by: KP Singh <kpsingh@xxxxxxxxxx> >> --- >> include/linux/bpf_local_storage.h | 10 + >> include/linux/bpf_lsm.h | 21 ++ >> include/linux/bpf_types.h | 3 + >> include/uapi/linux/bpf.h | 38 +++ >> kernel/bpf/Makefile | 1 + [...] ata *inode_storage_lookup(struct inode *inode, >> + struct bpf_map *map, >> + bool cacheit_lockit) >> +{ >> + struct bpf_local_storage *inode_storage; >> + struct bpf_local_storage_map *smap; >> + struct bpf_storage_blob *bsb; >> + >> + bsb = bpf_inode(inode); >> + if (!bsb) >> + return ERR_PTR(-ENOENT); > ERR_PTR is returned here... > >> + >> + inode_storage = rcu_dereference(bsb->storage); >> + if (!inode_storage) >> + return NULL; >> + [...] >> + kfree_rcu(local_storage, rcu); >> +} >> + >> + >> +static void *bpf_fd_inode_storage_lookup_elem(struct bpf_map *map, void *key) >> +{ >> + struct bpf_local_storage_data *sdata; >> + struct file *f; >> + int fd; >> + >> + fd = *(int *)key; >> + f = fcheck(fd); >> + if (!f) >> + return ERR_PTR(-EINVAL); >> + >> + get_file(f); >> + sdata = inode_storage_lookup(f->f_inode, map, true); >> + fput(f); >> + return sdata ? sdata->data : NULL; > sdata can be ERR_PTR here and a few other cases below. > > May be inode_storage_lookup() should just return NULL. I think returning NULL is a better option. Thanks! > >> +} >> + >> +static int bpf_fd_inode_storage_update_elem(struct bpf_map *map, void *key, >> + void *value, u64 map_flags) >> +{ >> + struct bpf_local_storage_data *sdata; >> + struct file *f; >> + int fd; >> + >> + fd = *(int *)key; >> + f = fcheck(fd); >> + if (!f) >> + return -EINVAL; >> + >> + get_file(f);> get_file() does atomic_long_inc() instead of atomic_long_inc_not_zero(). > I don't see how that helps here. Am I missing something? You are right, this should not not be an fcheck followed by a get_file rather fcheck followed by get_file_rcu: #define get_file_rcu_many(x, cnt) \ atomic_long_add_unless(&(x)->f_count, (cnt), 0) #define get_file_rcu(x) get_file_rcu_many((x), 1) #define file_count(x) atomic_long_read(&(x)->f_count) But there is an easier way than all of this and this is to use fget_raw which also calls get_file_rcu_many and ensures a non-zero count before getting a reference. - KP > >> + sdata = bpf_local_storage_update(f->f_inode, map, value, map_flags); >> + fput(f); >> + return PTR_ERR_OR_ZERO(sdata); >> +} >> +