2 * Copyright (c) 1991 - 1994, Julianne Frances Haugh
3 * Copyright (c) 1996 - 2001, Marek Michałkiewicz
4 * Copyright (c) 2003 - 2006, Tomasz Kłoczko
5 * Copyright (c) 2007 - 2010, Nicolas François
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. The name of the copyright holders or contributors may not be used to
17 * endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include <sys/types.h>
43 #include "prototypes.h"
46 #include <selinux/selinux.h>
47 #endif /* WITH_SELINUX */
48 #if defined(WITH_ACL) || defined(WITH_ATTR)
49 #include <attr/error_context.h>
50 #endif /* WITH_ACL || WITH_ATTR */
52 #include <acl/libacl.h>
55 #include <attr/libattr.h>
56 #endif /* WITH_ATTR */
58 static /*@null@*/const char *src_orig;
59 static /*@null@*/const char *dst_orig;
66 /*@dependent@*/struct link_name *ln_next;
68 static /*@exposed@*/struct link_name *links;
70 static int copy_entry (const char *src, const char *dst,
71 long int uid, long int gid);
72 static int copy_dir (const char *src, const char *dst,
73 const struct stat *statp, const struct timeval mt[],
74 long int uid, long int gid);
76 static char *readlink_malloc (const char *filename);
77 static int copy_symlink (const char *src, const char *dst,
78 const struct stat *statp, const struct timeval mt[],
79 long int uid, long int gid);
81 static int copy_hardlink (const char *src, const char *dst,
82 struct link_name *lp);
83 static int copy_special (const char *src, const char *dst,
84 const struct stat *statp, const struct timeval mt[],
85 long int uid, long int gid);
86 static int copy_file (const char *src, const char *dst,
87 const struct stat *statp, const struct timeval mt[],
88 long int uid, long int gid);
92 * selinux_file_context - Set the security context before any file or
95 * selinux_file_context () should be called before any creation of file,
96 * symlink, directory, ...
98 * Callers may have to Reset SELinux to create files with default
100 * setfscreatecon (NULL);
102 int selinux_file_context (const char *dst_name)
104 static bool selinux_checked = false;
105 static bool selinux_enabled;
106 security_context_t scontext = NULL;
108 if (!selinux_checked) {
109 selinux_enabled = is_selinux_enabled () > 0;
110 selinux_checked = true;
113 if (selinux_enabled) {
114 /* Get the default security context for this file */
115 if (matchpathcon (dst_name, 0, &scontext) < 0) {
116 if (security_getenforce () != 0) {
120 /* Set the security context for the next created file */
121 if (setfscreatecon (scontext) < 0) {
122 if (security_getenforce () != 0) {
130 #endif /* WITH_SELINUX */
132 #if defined(WITH_ACL) || defined(WITH_ATTR)
133 void error (struct error_context *ctx, const char *fmt, ...)
138 (void) fprintf (stderr, _("%s: "), Prog);
139 if (vfprintf (stderr, fmt, ap) != 0) {
140 (void) fputs (_(": "), stderr);
142 (void) fprintf (stderr, "%s\n", strerror (errno));
146 struct error_context ctx = {
149 #endif /* WITH_ACL || WITH_ATTR */
152 * remove_link - delete a link from the linked list
154 static void remove_link (/*@only@*/struct link_name *ln)
156 struct link_name *lp;
164 for (lp = links; NULL !=lp; lp = lp->ln_next) {
165 if (lp->ln_next == ln) {
176 lp->ln_next = lp->ln_next->ln_next;
182 * check_link - see if a file is really a link
185 static /*@exposed@*/ /*@null@*/struct link_name *check_link (const char *name, const struct stat *sb)
187 struct link_name *lp;
193 /* copy_tree () must be the entry point */
194 assert (NULL != src_orig);
195 assert (NULL != dst_orig);
197 for (lp = links; NULL != lp; lp = lp->ln_next) {
198 if ((lp->ln_dev == sb->st_dev) && (lp->ln_ino == sb->st_ino)) {
203 if (sb->st_nlink == 1) {
207 lp = (struct link_name *) xmalloc (sizeof *lp);
208 src_len = strlen (src_orig);
209 dst_len = strlen (dst_orig);
210 name_len = strlen (name);
211 lp->ln_dev = sb->st_dev;
212 lp->ln_ino = sb->st_ino;
213 lp->ln_count = sb->st_nlink;
214 len = name_len - src_len + dst_len + 1;
215 lp->ln_name = (char *) xmalloc (len);
216 snprintf (lp->ln_name, len, "%s%s", dst_orig, name + src_len);
224 * copy_tree - copy files in a directory tree
226 * copy_tree() walks a directory tree and copies ordinary files
229 int copy_tree (const char *src_root, const char *dst_root,
230 long int uid, long int gid)
233 bool set_orig = false;
238 * Make certain both directories exist. This routine is called
239 * after the home directory is created, or recursively after the
240 * target is created. It assumes the target directory exists.
243 if ( (access (src_root, F_OK) != 0)
244 || (access (dst_root, F_OK) != 0)) {
249 * Open the source directory and read each entry. Every file
250 * entry in the directory is copied with the UID and GID set
251 * to the provided values. As an added security feature only
252 * regular files (and directories ...) are copied, and no file
255 dir = opendir (src_root);
260 if (src_orig == NULL) {
265 while ((0 == err) && (ent = readdir (dir)) != NULL) {
267 * Skip the "." and ".." entries
269 if ((strcmp (ent->d_name, ".") != 0) &&
270 (strcmp (ent->d_name, "..") != 0)) {
273 size_t src_len = strlen (ent->d_name) + 2;
274 size_t dst_len = strlen (ent->d_name) + 2;
275 src_len += strlen (src_root);
276 dst_len += strlen (dst_root);
278 src_name = (char *) malloc (src_len);
279 dst_name = (char *) malloc (dst_len);
281 if ((NULL == src_name) || (NULL == dst_name)) {
285 * Build the filename for both the source and
286 * the destination files.
288 snprintf (src_name, src_len, "%s/%s",
289 src_root, ent->d_name);
290 snprintf (dst_name, dst_len, "%s/%s",
291 dst_root, ent->d_name);
293 err = copy_entry (src_name, dst_name, uid, gid);
295 if (NULL != src_name) {
298 if (NULL != dst_name) {
303 (void) closedir (dir);
311 /* Reset SELinux to create files with default contexts */
312 setfscreatecon (NULL);
313 #endif /* WITH_SELINUX */
315 /* FIXME: with the call to remove_link, we could also check that
316 * no links remain in links.
317 * assert (NULL == links); */
323 * copy_entry - copy the entry of a directory
325 * Copy the entry src to dst.
326 * Depending on the type of entry, this function will forward the
327 * request to copy_dir(), copy_symlink(), copy_hardlink(),
328 * copy_special(), or copy_file().
330 * The access and modification time will not be modified.
332 * The permissions will be set to uid/gid.
334 * If uid (resp. gid) is equal to -1, the user (resp. group) will
337 static int copy_entry (const char *src, const char *dst,
338 long int uid, long int gid)
342 struct link_name *lp;
343 struct timeval mt[2];
345 if (LSTAT (src, &sb) == -1) {
346 /* If we cannot stat the file, do not care. */
348 #ifdef HAVE_STRUCT_STAT_ST_ATIM
349 mt[0].tv_sec = sb.st_atim.tv_sec;
350 mt[0].tv_usec = sb.st_atim.tv_nsec / 1000;
351 #else /* !HAVE_STRUCT_STAT_ST_ATIM */
352 mt[0].tv_sec = sb.st_atime;
353 # ifdef HAVE_STRUCT_STAT_ST_ATIMENSEC
354 mt[0].tv_usec = sb.st_atimensec / 1000;
355 # else /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
357 # endif /* !HAVE_STRUCT_STAT_ST_ATIMENSEC */
358 #endif /* !HAVE_STRUCT_STAT_ST_ATIM */
360 #ifdef HAVE_STRUCT_STAT_ST_MTIM
361 mt[1].tv_sec = sb.st_mtim.tv_sec;
362 mt[1].tv_usec = sb.st_mtim.tv_nsec / 1000;
363 #else /* !HAVE_STRUCT_STAT_ST_MTIM */
364 mt[1].tv_sec = sb.st_mtime;
365 # ifdef HAVE_STRUCT_STAT_ST_MTIMENSEC
366 mt[1].tv_usec = sb.st_mtimensec / 1000;
367 # else /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
369 # endif /* !HAVE_STRUCT_STAT_ST_MTIMENSEC */
370 #endif /* !HAVE_STRUCT_STAT_ST_MTIM */
372 if (S_ISDIR (sb.st_mode)) {
373 err = copy_dir (src, dst, &sb, mt, uid, gid);
378 * Copy any symbolic links
381 else if (S_ISLNK (sb.st_mode)) {
382 err = copy_symlink (src, dst, &sb, mt, uid, gid);
387 * See if this is a previously copied link
390 else if ((lp = check_link (src, &sb)) != NULL) {
391 err = copy_hardlink (src, dst, lp);
395 * Deal with FIFOs and special files. The user really
396 * shouldn't have any of these, but it seems like it
397 * would be nice to copy everything ...
400 else if (!S_ISREG (sb.st_mode)) {
401 err = copy_special (src, dst, &sb, mt, uid, gid);
405 * Create the new file and copy the contents. The new
406 * file will be owned by the provided UID and GID values.
410 err = copy_file (src, dst, &sb, mt, uid, gid);
418 * copy_dir - copy a directory
420 * Copy a directory (recursively) from src to dst.
422 * statp, mt, uid, gid are used to set the access and modification and the
425 * Return 0 on success, -1 on error.
427 static int copy_dir (const char *src, const char *dst,
428 const struct stat *statp, const struct timeval mt[],
429 long int uid, long int gid)
434 * Create a new target directory, make it owned by
435 * the user and then recursively copy that directory.
439 selinux_file_context (dst);
440 #endif /* WITH_SELINUX */
441 if ( (mkdir (dst, statp->st_mode) != 0)
443 (uid == - 1) ? statp->st_uid : (uid_t) uid,
444 (gid == - 1) ? statp->st_gid : (gid_t) gid) != 0)
446 || (perm_copy_file (src, dst, &ctx) != 0)
447 #else /* !WITH_ACL */
448 || (chmod (dst, statp->st_mode) != 0)
449 #endif /* !WITH_ACL */
452 * If the third parameter is NULL, all extended attributes
453 * except those that define Access Control Lists are copied.
454 * ACLs are excluded by default because copying them between
455 * file systems with and without ACL support needs some
456 * additional logic so that no unexpected permissions result.
458 || (attr_copy_file (src, dst, NULL, &ctx) != 0)
459 #endif /* WITH_ATTR */
460 || (copy_tree (src, dst, uid, gid) != 0)
461 || (utimes (dst, mt) != 0)) {
470 * readlink_malloc - wrapper for readlink
472 * return NULL on error.
473 * The return string shall be freed by the caller.
475 static char *readlink_malloc (const char *filename)
481 char *buffer = (char *) malloc (size);
482 if (NULL == buffer) {
486 nchars = readlink (filename, buffer, size);
493 if ( (size_t) nchars < size) { /* The buffer was large enough */
494 /* readlink does not nul-terminate */
495 buffer[nchars] = '\0';
499 /* Try again with a bigger buffer */
506 * copy_symlink - copy a symlink
508 * Copy a symlink from src to dst.
510 * statp, mt, uid, gid are used to set the access and modification and the
513 * Return 0 on success, -1 on error.
515 static int copy_symlink (const char *src, const char *dst,
516 const struct stat *statp, const struct timeval mt[],
517 long int uid, long int gid)
521 /* copy_tree () must be the entry point */
522 assert (NULL != src_orig);
523 assert (NULL != dst_orig);
526 * Get the name of the file which the link points
527 * to. If that name begins with the original
528 * source directory name, that part of the link
529 * name will be replaced with the original
530 * destination directory name.
533 oldlink = readlink_malloc (src);
534 if (NULL == oldlink) {
538 /* If src was a link to an entry of the src_orig directory itself,
539 * create a link to the corresponding entry in the dst_orig
541 * FIXME: This may change a relative link to an absolute link
543 if (strncmp (oldlink, src_orig, strlen (src_orig)) == 0) {
544 size_t len = strlen (dst_orig) + strlen (oldlink) - strlen (src_orig) + 1;
545 char *dummy = (char *) malloc (len);
546 snprintf (dummy, len, "%s%s",
548 oldlink + strlen (src_orig));
554 selinux_file_context (dst);
555 #endif /* WITH_SELINUX */
556 if ( (symlink (oldlink, dst) != 0)
558 (uid == -1) ? statp->st_uid : (uid_t) uid,
559 (gid == -1) ? statp->st_gid : (gid_t) gid) != 0)) {
560 /* FIXME: there are no modes on symlinks, right?
561 * ACL could be copied, but this would be much more
562 * complex than calling perm_copy_file.
563 * Ditto for Extended Attributes.
564 * We currently only document that ACL and Extended
565 * Attributes are not copied.
573 /* 2007-10-18: We don't care about
574 * exit status of lutimes because
575 * it returns ENOSYS on many system
579 #endif /* HAVE_LUTIMES */
586 * copy_hardlink - copy a hardlink
588 * Copy a hardlink from src to dst.
590 * Return 0 on success, -1 on error.
592 static int copy_hardlink (const char *src, const char *dst,
593 struct link_name *lp)
595 /* TODO: selinux, ACL, Extended Attributes needed? */
597 if (link (lp->ln_name, dst) != 0) {
601 /* FIXME: why is it unlinked? This is a copy, not a move */
602 if (unlink (src) != 0) {
606 /* FIXME: idem, although it may never be used again */
607 /* If the file could be unlinked, decrement the links counter,
608 * and delete the file if it was the last reference */
610 if (lp->ln_count <= 0) {
618 * copy_special - copy a special file
620 * Copy a special file from src to dst.
622 * statp, mt, uid, gid are used to set the access and modification and the
625 * Return 0 on success, -1 on error.
627 static int copy_special (const char *src, const char *dst,
628 const struct stat *statp, const struct timeval mt[],
629 long int uid, long int gid)
634 selinux_file_context (dst);
635 #endif /* WITH_SELINUX */
637 if ( (mknod (dst, statp->st_mode & ~07777, statp->st_rdev) != 0)
639 (uid == -1) ? statp->st_uid : (uid_t) uid,
640 (gid == -1) ? statp->st_gid : (gid_t) gid) != 0)
642 || (perm_copy_file (src, dst, &ctx) != 0)
643 #else /* !WITH_ACL */
644 || (chmod (dst, statp->st_mode & 07777) != 0)
645 #endif /* !WITH_ACL */
648 * If the third parameter is NULL, all extended attributes
649 * except those that define Access Control Lists are copied.
650 * ACLs are excluded by default because copying them between
651 * file systems with and without ACL support needs some
652 * additional logic so that no unexpected permissions result.
654 || (attr_copy_file (src, dst, NULL, &ctx) != 0)
655 #endif /* WITH_ATTR */
656 || (utimes (dst, mt) != 0)) {
664 * copy_file - copy a file
666 * Copy a file from src to dst.
668 * statp, mt, uid, gid are used to set the access and modification and the
671 * Return 0 on success, -1 on error.
673 static int copy_file (const char *src, const char *dst,
674 const struct stat *statp, const struct timeval mt[],
675 long int uid, long int gid)
683 ifd = open (src, O_RDONLY);
688 selinux_file_context (dst);
689 #endif /* WITH_SELINUX */
690 ofd = open (dst, O_WRONLY | O_CREAT | O_TRUNC, statp->st_mode & 07777);
693 (uid == -1) ? statp->st_uid : (uid_t) uid,
694 (gid == -1) ? statp->st_gid : (gid_t) gid) != 0)
696 || (perm_copy_fd (src, ifd, dst, ofd, &ctx) != 0)
697 #else /* !WITH_ACL */
698 || (fchmod (ofd, statp->st_mode & 07777) != 0)
699 #endif /* !WITH_ACL */
702 * If the third parameter is NULL, all extended attributes
703 * except those that define Access Control Lists are copied.
704 * ACLs are excluded by default because copying them between
705 * file systems with and without ACL support needs some
706 * additional logic so that no unexpected permissions result.
708 || (attr_copy_fd (src, ifd, dst, ofd, NULL, &ctx) != 0)
709 #endif /* WITH_ATTR */
715 while ((cnt = read (ifd, buf, sizeof buf)) > 0) {
716 if (write (ofd, buf, (size_t)cnt) != cnt) {
725 if (futimes (ofd, mt) != 0) {
728 #endif /* HAVE_FUTIMES */
730 if (close (ofd) != 0) {
735 if (utimes(dst, mt) != 0) {
738 #endif /* !HAVE_FUTIMES */