1 /*
2 Bacula(R) - The Network Backup Solution
3
4 Copyright (C) 2000-2020 Kern Sibbald
5
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
8
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
13
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
16
17 Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /**
20 * Major refactoring of XATTR code written by:
21 *
22 * Radosław Korzeniewski, MMXVI
23 * radoslaw@korzeniewski.net, radekk@inteos.pl
24 * Inteos Sp. z o.o. http://www.inteos.pl/
25 *
26 */
27
28 #include "bacula.h"
29 #include "filed.h"
30 #include "bxattr_linux.h"
31
32 #if defined(HAVE_LINUX_OS)
33
34 /* check if XATTR support is enabled */
35 #if defined(HAVE_XATTR)
36
37 /*
38 * Define the supported XATTR streams for this OS
39 */
40 static const int os_xattr_streams[] = {
41 STREAM_XACL_LINUX_XATTR,
42 0
43 };
44
45 static const char *os_xattr_acl_skiplist[] = {
46 "system.posix_acl_access",
47 "system.posix_acl_default",
48 NULL
49 };
50
51 static const char *os_xattr_skiplist[] = {
52 NULL
53 };
54
55 /*
56 * OS specific constructor
57 */
BXATTR_Linux()58 BXATTR_Linux::BXATTR_Linux(){
59 set_xattr_streams(os_xattr_streams);
60 set_xattr_skiplists(os_xattr_skiplist, os_xattr_acl_skiplist);
61 };
62
63 /*
64 * Perform OS specific extended attribute backup
65 *
66 * in/out - check API at bxattr.h
67 */
os_backup_xattr(JCR * jcr,FF_PKT * ff_pkt)68 bRC_BXATTR BXATTR_Linux::os_backup_xattr (JCR *jcr, FF_PKT *ff_pkt){
69 return generic_backup_xattr(jcr, ff_pkt);
70 };
71
72 /*
73 * Perform OS specific XATTR restore. Runtime is called only when stream is supported by OS.
74 *
75 * in/out - check API at bxattr.h
76 */
os_restore_xattr(JCR * jcr,int stream,char * content,uint32_t length)77 bRC_BXATTR BXATTR_Linux::os_restore_xattr (JCR *jcr, int stream, char *content, uint32_t length){
78 return generic_restore_xattr(jcr, stream);
79 };
80
81 #define CIFS_XATTR "system.cifs_acl"
82 #define CIFS_XATTR_LEN 15
83
84 /*
85 * Return a list of xattr names in newly allocated pool memory and a length of the allocated buffer.
86 * It allocates a memory with poolmem subroutines every time a function is called, so it must be freed
87 * when not needed.
88 *
89 * in/out - check API at bxattr.h
90 */
os_get_xattr_names(JCR * jcr,POOLMEM ** pxlist,uint32_t * xlen)91 bRC_BXATTR BXATTR_Linux::os_get_xattr_names (JCR *jcr, POOLMEM ** pxlist, uint32_t * xlen){
92
93 int len, len2;
94 POOLMEM * list;
95 bool append_cifs=false;
96
97 /* check input data */
98 if (jcr == NULL || xlen == NULL || pxlist == NULL){
99 return bRC_BXATTR_inval;
100 }
101
102 /* With CIFS and CIFS2, the system.cifs_acl attribute holds the BackupRead
103 * information, but it is not listed by llistxattr
104 */
105 if (strncmp(get_current_fs(), "cifs", 4) == 0) {
106 append_cifs = true;
107 }
108
109 /* get the length of the extended attributes */
110 len = llistxattr(jcr->last_fname, NULL, 0);
111 switch (len){
112 case -1: {
113 berrno be;
114
115 switch (errno){
116 case ENOENT:
117 /* no file available, skip it */
118 return bRC_BXATTR_skip;
119 case EOPNOTSUPP:
120 /* no xattr supported on filesystem, clear a flag and skip it */
121 clear_flag(BXATTR_FLAG_NATIVE);
122 set_content(NULL);
123 return bRC_BXATTR_skip;
124 default:
125 Mmsg2(jcr->errmsg, _("llistxattr error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
126 Dmsg2(100, "llistxattr error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
127 return bRC_BXATTR_error;
128 }
129 break;
130 }
131 case 0:
132 if (append_cifs) { /* We have nothing, but the cifs attribute can be hidden */
133 len += CIFS_XATTR_LEN + 1;
134 } else {
135 /* xattr available but empty, skip it */
136 return bRC_BXATTR_skip;
137 }
138 default:
139 break;
140 }
141
142 /*
143 * allocate memory for the extented attribute list
144 * default size is a 4k for PM_BSOCK, which should be sufficient on almost all
145 * Linux system where xattrs a limited in size to single filesystem block ~4kB
146 * so we need to check required size
147 */
148 list = get_pool_memory(PM_BSOCK);
149 list = check_pool_memory_size(list, len + 1);
150 memset(list, 0, len + 1);
151
152 /* get the list of extended attributes names for a file */
153 len2 = llistxattr(jcr->last_fname, list, len);
154 switch (len2){
155 case -1: {
156 berrno be;
157
158 switch (errno){
159 case ENOENT:
160 /* no file available, skip it, first release allocated memory */
161 free_pool_memory(list);
162 return bRC_BXATTR_skip;
163 default:
164 Mmsg2(jcr->errmsg, _("llistxattr error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
165 Dmsg2(100, "llistxattr error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
166 free_pool_memory(list);
167 return bRC_BXATTR_error;
168 }
169 break;
170 }
171 default:
172 break;
173 }
174 /* ensure a list is nul terminated */
175 list[len2] = '\0';
176 if (append_cifs) {
177 len2 = xattr_list_append(list, len2, CIFS_XATTR, CIFS_XATTR_LEN);
178 }
179 /* setup return data */
180 *pxlist = list;
181 *xlen = len2;
182 return bRC_BXATTR_ok;
183 };
184
185 /*
186 * Return a value of the requested attribute name and a length of the allocated buffer.
187 * It allocates a memory with poolmem subroutines every time a function is called, so it must be freed
188 * when not needed.
189 *
190 * in/out - check API at bxattr.h
191 */
os_get_xattr_value(JCR * jcr,char * name,char ** pvalue,uint32_t * plen)192 bRC_BXATTR BXATTR_Linux::os_get_xattr_value (JCR *jcr, char * name, char ** pvalue, uint32_t * plen){
193
194 int len;
195 POOLMEM * value;
196
197 /* check input data */
198 if (jcr == NULL || name == NULL || plen == NULL || pvalue == NULL){
199 return bRC_BXATTR_inval;
200 }
201
202 /* get the length of the value for extended attribute */
203 len = lgetxattr(jcr->last_fname, name, NULL, 0);
204 switch (len){
205 case -1: {
206 berrno be;
207
208 switch (errno){
209 case ENOENT:
210 /* no file available, skip it */
211 return bRC_BXATTR_skip;
212 default:
213 /* XXX: what about ENOATTR error value? */
214 Mmsg2(jcr->errmsg, _("lgetxattr error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
215 Dmsg2(100, "lgetxattr error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
216 return bRC_BXATTR_error;
217 }
218 break;
219 }
220 default:
221 break;
222 }
223
224 if (len > 0){
225 /*
226 * allocate memory for the extented attribute value
227 * default size is a 256B for PM_MESSAGE, so we need to check required size
228 */
229 value = get_pool_memory(PM_MESSAGE);
230 value = check_pool_memory_size(value, len + 1);
231 memset(value, 0, len + 1);
232 /* value is not empty, get a data */
233 len = lgetxattr(jcr->last_fname, name, value, len);
234 switch (len){
235 case -1: {
236 berrno be;
237
238 switch (errno){
239 case ENOENT:
240 /* no file available, skip it, first release allocated memory */
241 free_pool_memory(value);
242 return bRC_BXATTR_skip;
243 default:
244 Mmsg2(jcr->errmsg, _("lgetxattr error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
245 Dmsg2(100, "lgetxattr error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
246 free_pool_memory(value);
247 return bRC_BXATTR_error;
248 }
249 break;
250 }
251 default:
252 break;
253 }
254 /* ensure a value is nul terminated */
255 value[len] = '\0';
256 } else {
257 /* empty value */
258 value = NULL;
259 len = 0;
260 }
261 /* setup return data */
262 *pvalue = value;
263 *plen = len;
264 return bRC_BXATTR_ok;
265 };
266
267 /*
268 * Low level OS specific runtime to set extended attribute on file
269 *
270 * in/out - check API at bxattr.h
271 */
os_set_xattr(JCR * jcr,BXATTR_xattr * xattr)272 bRC_BXATTR BXATTR_Linux::os_set_xattr (JCR *jcr, BXATTR_xattr *xattr){
273
274 /* check input data */
275 if (jcr == NULL || xattr == NULL){
276 return bRC_BXATTR_inval;
277 }
278
279 /* set extattr on file */
280 if (lsetxattr(jcr->last_fname, xattr->name, xattr->value, xattr->value_len, 0) != 0){
281 berrno be;
282
283 switch (errno){
284 case ENOENT:
285 break;
286 case ENOTSUP:
287 /*
288 * If the filesystem reports it doesn't support XATTR we clear the
289 * BXATTR_FLAG_NATIVE flag so we skip XATTR restores on all other files
290 * on the same filesystem. The BXATTR_FLAG_NATIVE flag gets set again
291 * when we change from one filesystem to an other.
292 */
293 clear_flag(BXATTR_FLAG_NATIVE);
294 Mmsg(jcr->errmsg, _("setxattr error on file \"%s\": filesystem doesn't support XATTR\n"), jcr->last_fname);
295 Dmsg3(100, "setxattr error name=%s value=%s file=%s filesystem doesn't support XATTR\n", xattr->name, xattr->value, jcr->last_fname);
296 break;
297 default:
298 Mmsg2(jcr->errmsg, _("setxattr error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
299 Dmsg2(100, "setxattr error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
300 return bRC_BXATTR_error;
301 }
302 }
303 return bRC_BXATTR_ok;
304 };
305
306 #endif /* HAVE_XATTR */
307
308 #endif /* HAVE_LINUX_OS */
309