]>
git.proxmox.com Git - ceph.git/blob - ceph/src/test/libcephfs/acl.cc
a6c4a65963d92778645610b7d264a9bdde1885bb
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2011 New Dream Network
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
14 #include "include/types.h"
15 #include "gtest/gtest.h"
16 #include "include/cephfs/libcephfs.h"
17 #include "include/ceph_fs.h"
18 #include "client/posix_acl.h"
22 #include <sys/types.h>
25 #include <sys/xattr.h>
28 static size_t acl_ea_size(int count
)
30 return sizeof(acl_ea_header
) + count
* sizeof(acl_ea_entry
);
33 static int acl_ea_count(size_t size
)
35 if (size
< sizeof(acl_ea_header
))
37 size
-= sizeof(acl_ea_header
);
38 if (size
% sizeof(acl_ea_entry
))
40 return size
/ sizeof(acl_ea_entry
);
43 static int check_acl_and_mode(const void *buf
, size_t size
, mode_t mode
)
45 const acl_ea_entry
*group_entry
= NULL
, *mask_entry
= NULL
;
46 const acl_ea_header
*header
= reinterpret_cast<const acl_ea_header
*>(buf
);
47 const acl_ea_entry
*entry
= header
->a_entries
;
48 int count
= (size
- sizeof(*header
)) / sizeof(*entry
);
49 for (int i
= 0; i
< count
; ++i
) {
50 __u16 tag
= entry
->e_tag
;
51 __u16 perm
= entry
->e_perm
;
54 if (perm
!= ((mode
>> 6) & 7))
64 if (perm
!= (mode
& 7))
76 __u16 perm
= mask_entry
->e_perm
;
77 if (perm
!= ((mode
>> 3) & 7))
82 __u16 perm
= group_entry
->e_perm
;
83 if (perm
!= ((mode
>> 3) & 7))
89 static int generate_test_acl(void *buf
, size_t size
, mode_t mode
)
91 if (acl_ea_count(size
) != 5)
93 acl_ea_header
*header
= reinterpret_cast<acl_ea_header
*>(buf
);
94 header
->a_version
= (__u32
)ACL_EA_VERSION
;
95 acl_ea_entry
*entry
= header
->a_entries
;
96 entry
->e_tag
= ACL_USER_OBJ
;
97 entry
->e_perm
= (mode
>> 6) & 7;
99 entry
->e_tag
= ACL_USER
;
101 entry
->e_id
= getuid();
103 entry
->e_tag
= ACL_GROUP_OBJ
;
104 entry
->e_perm
= (mode
>> 3) & 7;
106 entry
->e_tag
= ACL_MASK
;
109 entry
->e_tag
= ACL_OTHER
;
110 entry
->e_perm
= mode
& 7;
114 static int generate_empty_acl(void *buf
, size_t size
, mode_t mode
)
117 if (acl_ea_count(size
) != 3)
119 acl_ea_header
*header
= reinterpret_cast<acl_ea_header
*>(buf
);
120 header
->a_version
= (__u32
)ACL_EA_VERSION
;
121 acl_ea_entry
*entry
= header
->a_entries
;
122 entry
->e_tag
= ACL_USER_OBJ
;
123 entry
->e_perm
= (mode
>> 6) & 7;
125 entry
->e_tag
= ACL_GROUP_OBJ
;
126 entry
->e_perm
= (mode
>> 3) & 7;
128 entry
->e_tag
= ACL_OTHER
;
129 entry
->e_perm
= mode
& 7;
134 struct ceph_mount_info
*cmount
;
135 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
136 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
137 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
138 ASSERT_EQ(0, ceph_conf_set(cmount
, "client_acl_type", "posix_acl"));
139 ASSERT_EQ(0, ceph_conf_set(cmount
, "client_permissions", "0"));
142 sprintf(test_file
, "file1_setacl_%d", getpid());
144 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0600);
146 // change ownership to nobody -- we assume nobody exists and id is always 65534
147 ASSERT_EQ(ceph_fchown(cmount
, fd
, 65534, 65534), 0);
149 ASSERT_EQ(0, ceph_conf_set(cmount
, "client_permissions", "1"));
150 ASSERT_EQ(ceph_open(cmount
, test_file
, O_RDWR
, 0), -EACCES
);
151 ASSERT_EQ(0, ceph_conf_set(cmount
, "client_permissions", "0"));
153 size_t acl_buf_size
= acl_ea_size(5);
154 void *acl_buf
= malloc(acl_buf_size
);
155 ASSERT_EQ(generate_test_acl(acl_buf
, acl_buf_size
, 0750), 0);
157 // can't set default acl for non-directory
158 ASSERT_EQ(ceph_fsetxattr(cmount
, fd
, ACL_EA_DEFAULT
, acl_buf
, acl_buf_size
, 0), -EACCES
);
159 ASSERT_EQ(ceph_fsetxattr(cmount
, fd
, ACL_EA_ACCESS
, acl_buf
, acl_buf_size
, 0), 0);
161 int tmpfd
= ceph_open(cmount
, test_file
, O_RDWR
, 0);
163 ceph_close(cmount
, tmpfd
);
165 struct ceph_statx stx
;
166 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_MODE
, 0), 0);
167 // mode was modified according to ACL
168 ASSERT_EQ(stx
.stx_mode
& 0777u, 0770u);
169 ASSERT_EQ(check_acl_and_mode(acl_buf
, acl_buf_size
, stx
.stx_mode
), 0);
171 acl_buf_size
= acl_ea_size(3);
172 // setting ACL that is equivalent to file mode
173 ASSERT_EQ(generate_empty_acl(acl_buf
, acl_buf_size
, 0600), 0);
174 ASSERT_EQ(ceph_fsetxattr(cmount
, fd
, ACL_EA_ACCESS
, acl_buf
, acl_buf_size
, 0), 0);
176 ASSERT_EQ(ceph_fgetxattr(cmount
, fd
, ACL_EA_ACCESS
, NULL
, 0), -ENODATA
);
178 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_MODE
, 0), 0);
179 // mode was modified according to ACL
180 ASSERT_EQ(stx
.stx_mode
& 0777u, 0600u);
183 ceph_close(cmount
, fd
);
184 ceph_shutdown(cmount
);
188 struct ceph_mount_info
*cmount
;
189 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
190 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
191 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
192 ASSERT_EQ(0, ceph_conf_set(cmount
, "client_acl_type", "posix_acl"));
195 sprintf(test_file
, "file1_acl_chmod_%d", getpid());
197 int fd
= ceph_open(cmount
, test_file
, O_CREAT
|O_RDWR
, 0600);
200 int acl_buf_size
= acl_ea_size(5);
201 void *acl_buf
= malloc(acl_buf_size
);
202 ASSERT_EQ(generate_test_acl(acl_buf
, acl_buf_size
, 0775), 0);
203 ASSERT_EQ(ceph_fsetxattr(cmount
, fd
, ACL_EA_ACCESS
, acl_buf
, acl_buf_size
, 0), 0);
205 struct ceph_statx stx
;
206 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_MODE
, 0), 0);
207 // mode was updated according to ACL
208 ASSERT_EQ(stx
.stx_mode
& 0777u, 0775u);
211 ASSERT_EQ(ceph_fchmod(cmount
, fd
, 0640), 0);
213 ASSERT_EQ(ceph_fstatx(cmount
, fd
, &stx
, CEPH_STATX_MODE
, 0), 0);
214 ASSERT_EQ(stx
.stx_mode
& 0777u, 0640u);
216 // ACL was updated according to mode
217 ASSERT_EQ(ceph_fgetxattr(cmount
, fd
, ACL_EA_ACCESS
, acl_buf
, acl_buf_size
), acl_buf_size
);
218 ASSERT_EQ(check_acl_and_mode(acl_buf
, acl_buf_size
, stx
.stx_mode
), 0);
221 ceph_close(cmount
, fd
);
222 ceph_shutdown(cmount
);
225 TEST(ACL
, DefaultACL
) {
226 struct ceph_mount_info
*cmount
;
227 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
228 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
229 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
230 ASSERT_EQ(0, ceph_conf_set(cmount
, "client_acl_type", "posix_acl"));
232 int acl_buf_size
= acl_ea_size(5);
233 void *acl1_buf
= malloc(acl_buf_size
);
234 void *acl2_buf
= malloc(acl_buf_size
);
236 ASSERT_EQ(generate_test_acl(acl1_buf
, acl_buf_size
, 0750), 0);
239 sprintf(test_dir1
, "dir1_acl_default_%d", getpid());
240 ASSERT_EQ(ceph_mkdir(cmount
, test_dir1
, 0750), 0);
243 ASSERT_EQ(ceph_setxattr(cmount
, test_dir1
, ACL_EA_DEFAULT
, acl1_buf
, acl_buf_size
, 0), 0);
246 sprintf(test_dir2
, "%s/dir2", test_dir1
);
247 ASSERT_EQ(ceph_mkdir(cmount
, test_dir2
, 0755), 0);
249 // inherit default acl
250 ASSERT_EQ(ceph_getxattr(cmount
, test_dir2
, ACL_EA_DEFAULT
, acl2_buf
, acl_buf_size
), acl_buf_size
);
251 ASSERT_EQ(memcmp(acl1_buf
, acl2_buf
, acl_buf_size
), 0);
253 // mode and ACL are updated
254 ASSERT_EQ(ceph_getxattr(cmount
, test_dir2
, ACL_EA_ACCESS
, acl2_buf
, acl_buf_size
), acl_buf_size
);
256 struct ceph_statx stx
;
257 ASSERT_EQ(ceph_statx(cmount
, test_dir2
, &stx
, CEPH_STATX_MODE
, 0), 0);
258 // other bits of mode &= acl other perm
259 ASSERT_EQ(stx
.stx_mode
& 0777u, 0750u);
260 ASSERT_EQ(check_acl_and_mode(acl2_buf
, acl_buf_size
, stx
.stx_mode
), 0);
263 char test_file1
[262];
264 sprintf(test_file1
, "%s/file1", test_dir1
);
265 int fd
= ceph_open(cmount
, test_file1
, O_CREAT
|O_RDWR
, 0666);
269 ASSERT_EQ(ceph_fgetxattr(cmount
, fd
, ACL_EA_DEFAULT
, NULL
, 0), -ENODATA
);
271 // mode and ACL are updated
272 ASSERT_EQ(ceph_fgetxattr(cmount
, fd
, ACL_EA_ACCESS
, acl2_buf
, acl_buf_size
), acl_buf_size
);
274 struct ceph_statx stx
;
275 ASSERT_EQ(ceph_statx(cmount
, test_file1
, &stx
, CEPH_STATX_MODE
, 0), 0);
276 // other bits of mode &= acl other perm
277 ASSERT_EQ(stx
.stx_mode
& 0777u, 0660u);
278 ASSERT_EQ(check_acl_and_mode(acl2_buf
, acl_buf_size
, stx
.stx_mode
), 0);
283 ceph_close(cmount
, fd
);
284 ceph_shutdown(cmount
);
287 TEST(ACL
, Disabled
) {
288 struct ceph_mount_info
*cmount
;
289 ASSERT_EQ(0, ceph_create(&cmount
, NULL
));
290 ASSERT_EQ(0, ceph_conf_read_file(cmount
, NULL
));
291 ASSERT_EQ(0, ceph_mount(cmount
, "/"));
292 ASSERT_EQ(0, ceph_conf_set(cmount
, "client_acl_type", ""));
294 size_t acl_buf_size
= acl_ea_size(3);
295 void *acl_buf
= malloc(acl_buf_size
);
296 ASSERT_EQ(generate_empty_acl(acl_buf
, acl_buf_size
, 0755), 0);
299 sprintf(test_dir
, "dir1_acl_disabled_%d", getpid());
300 ASSERT_EQ(ceph_mkdir(cmount
, test_dir
, 0750), 0);
302 ASSERT_EQ(ceph_setxattr(cmount
, test_dir
, ACL_EA_DEFAULT
, acl_buf
, acl_buf_size
, 0), -EOPNOTSUPP
);
303 ASSERT_EQ(ceph_setxattr(cmount
, test_dir
, ACL_EA_ACCESS
, acl_buf
, acl_buf_size
, 0), -EOPNOTSUPP
);
304 ASSERT_EQ(ceph_getxattr(cmount
, test_dir
, ACL_EA_DEFAULT
, acl_buf
, acl_buf_size
), -EOPNOTSUPP
);
305 ASSERT_EQ(ceph_getxattr(cmount
, test_dir
, ACL_EA_ACCESS
, acl_buf
, acl_buf_size
), -EOPNOTSUPP
);
308 ceph_shutdown(cmount
);