xref: /openbmc/linux/fs/jfs/acl.c (revision 59e34e39)
1  // SPDX-License-Identifier: GPL-2.0-or-later
2  /*
3   *   Copyright (C) International Business Machines  Corp., 2002-2004
4   *   Copyright (C) Andreas Gruenbacher, 2001
5   *   Copyright (C) Linus Torvalds, 1991, 1992
6   */
7  
8  #include <linux/sched.h>
9  #include <linux/slab.h>
10  #include <linux/fs.h>
11  #include <linux/posix_acl_xattr.h>
12  #include "jfs_incore.h"
13  #include "jfs_txnmgr.h"
14  #include "jfs_xattr.h"
15  #include "jfs_acl.h"
16  
17  struct posix_acl *jfs_get_acl(struct inode *inode, int type, bool rcu)
18  {
19  	struct posix_acl *acl;
20  	char *ea_name;
21  	int size;
22  	char *value = NULL;
23  
24  	if (rcu)
25  		return ERR_PTR(-ECHILD);
26  
27  	switch(type) {
28  		case ACL_TYPE_ACCESS:
29  			ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
30  			break;
31  		case ACL_TYPE_DEFAULT:
32  			ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
33  			break;
34  		default:
35  			return ERR_PTR(-EINVAL);
36  	}
37  
38  	size = __jfs_getxattr(inode, ea_name, NULL, 0);
39  
40  	if (size > 0) {
41  		value = kmalloc(size, GFP_KERNEL);
42  		if (!value)
43  			return ERR_PTR(-ENOMEM);
44  		size = __jfs_getxattr(inode, ea_name, value, size);
45  	}
46  
47  	if (size < 0) {
48  		if (size == -ENODATA)
49  			acl = NULL;
50  		else
51  			acl = ERR_PTR(size);
52  	} else {
53  		acl = posix_acl_from_xattr(&init_user_ns, value, size);
54  	}
55  	kfree(value);
56  	return acl;
57  }
58  
59  static int __jfs_set_acl(tid_t tid, struct inode *inode, int type,
60  		       struct posix_acl *acl)
61  {
62  	char *ea_name;
63  	int rc;
64  	int size = 0;
65  	char *value = NULL;
66  
67  	switch (type) {
68  	case ACL_TYPE_ACCESS:
69  		ea_name = XATTR_NAME_POSIX_ACL_ACCESS;
70  		break;
71  	case ACL_TYPE_DEFAULT:
72  		ea_name = XATTR_NAME_POSIX_ACL_DEFAULT;
73  		break;
74  	default:
75  		return -EINVAL;
76  	}
77  
78  	if (acl) {
79  		size = posix_acl_xattr_size(acl->a_count);
80  		value = kmalloc(size, GFP_KERNEL);
81  		if (!value)
82  			return -ENOMEM;
83  		rc = posix_acl_to_xattr(&init_user_ns, acl, value, size);
84  		if (rc < 0)
85  			goto out;
86  	}
87  	rc = __jfs_setxattr(tid, inode, ea_name, value, size, 0);
88  out:
89  	kfree(value);
90  
91  	if (!rc)
92  		set_cached_acl(inode, type, acl);
93  
94  	return rc;
95  }
96  
97  int jfs_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,
98  		struct posix_acl *acl, int type)
99  {
100  	int rc;
101  	tid_t tid;
102  	int update_mode = 0;
103  	struct inode *inode = d_inode(dentry);
104  	umode_t mode = inode->i_mode;
105  
106  	tid = txBegin(inode->i_sb, 0);
107  	mutex_lock(&JFS_IP(inode)->commit_mutex);
108  	if (type == ACL_TYPE_ACCESS && acl) {
109  		rc = posix_acl_update_mode(&nop_mnt_idmap, inode, &mode, &acl);
110  		if (rc)
111  			goto end_tx;
112  		if (mode != inode->i_mode)
113  			update_mode = 1;
114  	}
115  	rc = __jfs_set_acl(tid, inode, type, acl);
116  	if (!rc) {
117  		if (update_mode) {
118  			inode->i_mode = mode;
119  			inode_set_ctime_current(inode);
120  			mark_inode_dirty(inode);
121  		}
122  		rc = txCommit(tid, 1, &inode, 0);
123  	}
124  end_tx:
125  	txEnd(tid);
126  	mutex_unlock(&JFS_IP(inode)->commit_mutex);
127  	return rc;
128  }
129  
130  int jfs_init_acl(tid_t tid, struct inode *inode, struct inode *dir)
131  {
132  	struct posix_acl *default_acl, *acl;
133  	int rc = 0;
134  
135  	rc = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl);
136  	if (rc)
137  		return rc;
138  
139  	if (default_acl) {
140  		rc = __jfs_set_acl(tid, inode, ACL_TYPE_DEFAULT, default_acl);
141  		posix_acl_release(default_acl);
142  	} else {
143  		inode->i_default_acl = NULL;
144  	}
145  
146  	if (acl) {
147  		if (!rc)
148  			rc = __jfs_set_acl(tid, inode, ACL_TYPE_ACCESS, acl);
149  		posix_acl_release(acl);
150  	} else {
151  		inode->i_acl = NULL;
152  	}
153  
154  	JFS_IP(inode)->mode2 = (JFS_IP(inode)->mode2 & 0xffff0000) |
155  			       inode->i_mode;
156  
157  	return rc;
158  }
159