11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * Copyright (C) International Business Machines Corp., 2002-2004
41da177e4SLinus Torvalds * Copyright (C) Andreas Gruenbacher, 2001
51da177e4SLinus Torvalds * Copyright (C) Linus Torvalds, 1991, 1992
61da177e4SLinus Torvalds */
71da177e4SLinus Torvalds
81da177e4SLinus Torvalds #include <linux/sched.h>
95a0e3ad6STejun Heo #include <linux/slab.h>
101da177e4SLinus Torvalds #include <linux/fs.h>
119a59f452SChristoph Hellwig #include <linux/posix_acl_xattr.h>
121da177e4SLinus Torvalds #include "jfs_incore.h"
134f4b401bSDave Kleikamp #include "jfs_txnmgr.h"
141da177e4SLinus Torvalds #include "jfs_xattr.h"
151da177e4SLinus Torvalds #include "jfs_acl.h"
161da177e4SLinus Torvalds
jfs_get_acl(struct inode * inode,int type,bool rcu)170cad6246SMiklos Szeredi struct posix_acl *jfs_get_acl(struct inode *inode, int type, bool rcu)
181da177e4SLinus Torvalds {
191da177e4SLinus Torvalds struct posix_acl *acl;
201da177e4SLinus Torvalds char *ea_name;
211da177e4SLinus Torvalds int size;
221da177e4SLinus Torvalds char *value = NULL;
231da177e4SLinus Torvalds
240cad6246SMiklos Szeredi if (rcu)
250cad6246SMiklos Szeredi return ERR_PTR(-ECHILD);
260cad6246SMiklos Szeredi
271da177e4SLinus Torvalds switch(type) {
281da177e4SLinus Torvalds case ACL_TYPE_ACCESS:
2997d79299SAndreas Gruenbacher ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
301da177e4SLinus Torvalds break;
311da177e4SLinus Torvalds case ACL_TYPE_DEFAULT:
3297d79299SAndreas Gruenbacher ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
331da177e4SLinus Torvalds break;
341da177e4SLinus Torvalds default:
351da177e4SLinus Torvalds return ERR_PTR(-EINVAL);
361da177e4SLinus Torvalds }
371da177e4SLinus Torvalds
381da177e4SLinus Torvalds size = __jfs_getxattr(inode, ea_name, NULL, 0);
391da177e4SLinus Torvalds
401da177e4SLinus Torvalds if (size > 0) {
411da177e4SLinus Torvalds value = kmalloc(size, GFP_KERNEL);
421da177e4SLinus Torvalds if (!value)
431da177e4SLinus Torvalds return ERR_PTR(-ENOMEM);
441da177e4SLinus Torvalds size = __jfs_getxattr(inode, ea_name, value, size);
451da177e4SLinus Torvalds }
461da177e4SLinus Torvalds
471da177e4SLinus Torvalds if (size < 0) {
48073aaa1bSAl Viro if (size == -ENODATA)
491da177e4SLinus Torvalds acl = NULL;
50073aaa1bSAl Viro else
511da177e4SLinus Torvalds acl = ERR_PTR(size);
521da177e4SLinus Torvalds } else {
535f3a4a28SEric W. Biederman acl = posix_acl_from_xattr(&init_user_ns, value, size);
541da177e4SLinus Torvalds }
551da177e4SLinus Torvalds kfree(value);
561da177e4SLinus Torvalds return acl;
571da177e4SLinus Torvalds }
581da177e4SLinus Torvalds
__jfs_set_acl(tid_t tid,struct inode * inode,int type,struct posix_acl * acl)592cc6a5a0SChristoph Hellwig static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
604f4b401bSDave Kleikamp struct posix_acl *acl)
611da177e4SLinus Torvalds {
621da177e4SLinus Torvalds char *ea_name;
631da177e4SLinus Torvalds int rc;
641da177e4SLinus Torvalds int size = 0;
651da177e4SLinus Torvalds char *value = NULL;
661da177e4SLinus Torvalds
671da177e4SLinus Torvalds switch (type) {
681da177e4SLinus Torvalds case ACL_TYPE_ACCESS:
6997d79299SAndreas Gruenbacher ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
701da177e4SLinus Torvalds break;
711da177e4SLinus Torvalds case ACL_TYPE_DEFAULT:
7297d79299SAndreas Gruenbacher ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
731da177e4SLinus Torvalds break;
741da177e4SLinus Torvalds default:
751da177e4SLinus Torvalds return -EINVAL;
761da177e4SLinus Torvalds }
772cc6a5a0SChristoph Hellwig
781da177e4SLinus Torvalds if (acl) {
799a59f452SChristoph Hellwig size = posix_acl_xattr_size(acl->a_count);
801da177e4SLinus Torvalds value = kmalloc(size, GFP_KERNEL);
811da177e4SLinus Torvalds if (!value)
821da177e4SLinus Torvalds return -ENOMEM;
835f3a4a28SEric W. Biederman rc = posix_acl_to_xattr(&init_user_ns, acl, value, size);
841da177e4SLinus Torvalds if (rc < 0)
851da177e4SLinus Torvalds goto out;
861da177e4SLinus Torvalds }
874f4b401bSDave Kleikamp rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
881da177e4SLinus Torvalds out:
891da177e4SLinus Torvalds kfree(value);
901da177e4SLinus Torvalds
91073aaa1bSAl Viro if (!rc)
92073aaa1bSAl Viro set_cached_acl(inode, type, acl);
93073aaa1bSAl Viro
941da177e4SLinus Torvalds return rc;
951da177e4SLinus Torvalds }
961da177e4SLinus Torvalds
jfs_set_acl(struct mnt_idmap * idmap,struct dentry * dentry,struct posix_acl * acl,int type)9713e83a49SChristian Brauner int jfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
98549c7297SChristian Brauner struct posix_acl *acl, int type)
991da177e4SLinus Torvalds {
1001da177e4SLinus Torvalds int rc;
101bc26ab5fSAl Viro tid_t tid;
102f070e5acSErnesto A. Fernández int update_mode = 0;
103138060baSChristian Brauner struct inode *inode = d_inode(dentry);
104f070e5acSErnesto A. Fernández umode_t mode = inode->i_mode;
1051da177e4SLinus Torvalds
106bc26ab5fSAl Viro tid = txBegin(inode->i_sb, 0);
1071de87444SIngo Molnar mutex_lock(&JFS_IP(inode)->commit_mutex);
1089bcf66c7SJan Kara if (type == ACL_TYPE_ACCESS && acl) {
109700b7940SChristian Brauner rc = posix_acl_update_mode(&nop_mnt_idmap, inode, &mode, &acl);
1109bcf66c7SJan Kara if (rc)
1119bcf66c7SJan Kara goto end_tx;
1127ca5e8f0SChengguang Xu if (mode != inode->i_mode)
113f070e5acSErnesto A. Fernández update_mode = 1;
114f070e5acSErnesto A. Fernández }
115f070e5acSErnesto A. Fernández rc = __jfs_set_acl(tid, inode, type, acl);
116f070e5acSErnesto A. Fernández if (!rc) {
117f070e5acSErnesto A. Fernández if (update_mode) {
118f070e5acSErnesto A. Fernández inode->i_mode = mode;
119*ad9dc5dfSJeff Layton inode_set_ctime_current(inode);
1209bcf66c7SJan Kara mark_inode_dirty(inode);
1219bcf66c7SJan Kara }
1224f4b401bSDave Kleikamp rc = txCommit(tid, 1, &inode, 0);
123f070e5acSErnesto A. Fernández }
1249bcf66c7SJan Kara end_tx:
1254f4b401bSDave Kleikamp txEnd(tid);
1261de87444SIngo Molnar mutex_unlock(&JFS_IP(inode)->commit_mutex);
1272cc6a5a0SChristoph Hellwig return rc;
1282cc6a5a0SChristoph Hellwig }
1291da177e4SLinus Torvalds
jfs_init_acl(tid_t tid,struct inode * inode,struct inode * dir)1302cc6a5a0SChristoph Hellwig int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
1312cc6a5a0SChristoph Hellwig {
1322cc6a5a0SChristoph Hellwig struct posix_acl *default_acl, *acl;
1332cc6a5a0SChristoph Hellwig int rc = 0;
1342cc6a5a0SChristoph Hellwig
1352cc6a5a0SChristoph Hellwig rc = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
1362cc6a5a0SChristoph Hellwig if (rc)
1372cc6a5a0SChristoph Hellwig return rc;
1382cc6a5a0SChristoph Hellwig
1392cc6a5a0SChristoph Hellwig if (default_acl) {
1402cc6a5a0SChristoph Hellwig rc = __jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, default_acl);
1412cc6a5a0SChristoph Hellwig posix_acl_release(default_acl);
142e8d4ceebSChengguang Xu } else {
143e8d4ceebSChengguang Xu inode->i_default_acl = NULL;
1442cc6a5a0SChristoph Hellwig }
1452cc6a5a0SChristoph Hellwig
1462cc6a5a0SChristoph Hellwig if (acl) {
1472cc6a5a0SChristoph Hellwig if (!rc)
1482cc6a5a0SChristoph Hellwig rc = __jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
149bc26ab5fSAl Viro posix_acl_release(acl);
150e8d4ceebSChengguang Xu } else {
151e8d4ceebSChengguang Xu inode->i_acl = NULL;
1522cc6a5a0SChristoph Hellwig }
1532cc6a5a0SChristoph Hellwig
1542cc6a5a0SChristoph Hellwig JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
1552cc6a5a0SChristoph Hellwig inode->i_mode;
1562cc6a5a0SChristoph Hellwig
1571da177e4SLinus Torvalds return rc;
1581da177e4SLinus Torvalds }
159