735
/* return -errno on failure, or 0 on success */
737
virFileOpenAsNoFork(const char *path, int openflags, mode_t mode,
738
uid_t uid, gid_t gid, unsigned int flags)
766
/* virFileOpenForceOwnerMode() - an internal utility function called
767
* only by virFileOpenAs(). Sets the owner and mode of the file
768
* opened as "fd" if it's not correct AND the flags say it should be
771
virFileOpenForceOwnerMode(const char *path, int fd, mode_t mode,
772
uid_t uid, gid_t gid, unsigned int flags)
777
if (!(flags & (VIR_FILE_OPEN_FORCE_OWNER | VIR_FILE_OPEN_FORCE_MODE)))
780
if (fstat(fd, &st) == -1) {
782
virReportSystemError(errno, _("stat of '%s' failed"), path);
785
/* NB: uid:gid are never "-1" (default) at this point - the caller
786
* has always changed -1 to the value of get[gu]id().
788
if ((flags & VIR_FILE_OPEN_FORCE_OWNER) &&
789
((st.st_uid != uid) || (st.st_gid != gid)) &&
790
(fchown(fd, uid, gid) < 0)) {
792
virReportSystemError(errno,
793
_("cannot chown '%s' to (%u, %u)"),
794
path, (unsigned int) uid,
798
if ((flags & VIR_FILE_OPEN_FORCE_MODE) &&
799
((mode & (S_IRWXU|S_IRWXG|S_IRWXO)) !=
800
(st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO))) &&
801
(fchmod(fd, mode) < 0)) {
803
virReportSystemError(errno,
804
_("cannot set mode of '%s' to %04o"),
811
/* virFileOpenForked() - an internal utility function called only by
812
* virFileOpenAs(). It forks, then the child does setuid+setgid to
813
* given uid:gid and attempts to open the file, while the parent just
814
* calls recvfd to get the open fd back from the child. returns the
815
* fd, or -errno if there is an error. */
817
virFileOpenForked(const char *path, int openflags, mode_t mode,
818
uid_t uid, gid_t gid, unsigned int flags)
821
int waitret, status, ret = 0;
743
if ((fd = open(path, openflags, mode)) < 0) {
745
virReportSystemError(errno, _("failed to create file '%s'"),
750
/* VIR_FILE_OPEN_AS_UID in flags means we are running in a child process
751
* owned by uid and gid */
752
if (!(flags & VIR_FILE_OPEN_AS_UID)) {
755
if (fstat(fd, &st) == -1) {
757
virReportSystemError(errno, _("stat of '%s' failed"), path);
760
if (((st.st_uid != uid) || (st.st_gid != gid))
761
&& (openflags & O_CREAT)
762
&& (fchown(fd, uid, gid) < 0)) {
764
virReportSystemError(errno, _("cannot chown '%s' to (%u, %u)"),
765
path, (unsigned int) uid, (unsigned int) gid);
770
if ((flags & VIR_FILE_OPEN_FORCE_PERMS)
771
&& (fchmod(fd, mode) < 0)) {
773
virReportSystemError(errno,
774
_("cannot set mode of '%s' to %04o"),
823
int pair[2] = { -1, -1 };
826
/* parent is running as root, but caller requested that the
827
* file be opened as some other user and/or group). The
828
* following dance avoids problems caused by root-squashing
831
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) < 0) {
833
virReportSystemError(errno,
834
_("failed to create socket needed for '%s'"),
839
forkRet = virFork(&pid);
847
VIR_FORCE_CLOSE(pair[0]); /* preserves errno */
849
/* error encountered and logged in virFork() after the fork. */
854
/* set desired uid/gid, then attempt to create the file */
856
if (virSetUIDGID(uid, gid) < 0) {
861
if ((fd = open(path, openflags, mode)) < 0) {
863
virReportSystemError(errno,
864
_("child process failed to create file '%s'"),
869
/* File is successfully open. Set permissions if requested. */
870
ret = virFileOpenForceOwnerMode(path, fd, mode, uid, gid, flags);
875
ret = sendfd(pair[1], fd);
876
} while (ret < 0 && errno == EINTR);
880
virReportSystemError(errno, "%s",
881
_("child process failed to send fd to parent"));
886
/* ret tracks -errno on failure, but exit value must be positive.
887
* If the child exits with EACCES, then the parent tries again. */
888
/* XXX This makes assumptions about errno being < 255, which is
889
* not true on Hurd. */
890
VIR_FORCE_CLOSE(pair[1]);
895
if ((ret & 0xff) != ret) {
896
VIR_WARN("unable to pass desired return value %d", ret);
904
VIR_FORCE_CLOSE(pair[1]);
907
fd = recvfd(pair[0], 0);
908
} while (fd < 0 && errno == EINTR);
909
VIR_FORCE_CLOSE(pair[0]); /* NB: this preserves errno */
911
if (fd < 0 && errno != EACCES) {
913
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR);
917
/* wait for child to complete, and retrieve its exit code */
918
while ((waitret = waitpid(pid, &status, 0) == -1)
919
&& (errno == EINTR));
922
virReportSystemError(errno,
923
_("failed to wait for child creating '%s'"),
928
if (!WIFEXITED(status) || (ret = -WEXITSTATUS(status)) == -EACCES ||
930
/* fall back to the simpler method, which works better in
933
if (flags & VIR_FILE_OPEN_NOFORK) {
934
/* If we had already tried opening w/o fork+setuid and
935
* failed, no sense trying again. Just set return the
936
* original errno that we got at that time (by
937
* definition, always either EACCES or EPERM - EACCES
942
if ((fd = open(path, openflags, mode)) < 0)
944
ret = virFileOpenForceOwnerMode(path, fd, mode, uid, gid, flags);
785
/* return -errno on failure, or 0 on success */
786
static int virDirCreateNoFork(const char *path, mode_t mode, uid_t uid, gid_t gid,
787
unsigned int flags) {
791
if ((mkdir(path, mode) < 0)
792
&& !((errno == EEXIST) && (flags & VIR_DIR_CREATE_ALLOW_EXIST))) {
794
virReportSystemError(errno, _("failed to create directory '%s'"),
799
if (stat(path, &st) == -1) {
801
virReportSystemError(errno, _("stat of '%s' failed"), path);
804
if (((st.st_uid != uid) || (st.st_gid != gid))
805
&& (chown(path, uid, gid) < 0)) {
807
virReportSystemError(errno, _("cannot chown '%s' to (%u, %u)"),
808
path, (unsigned int) uid, (unsigned int) gid);
811
if ((flags & VIR_DIR_CREATE_FORCE_PERMS)
812
&& (chmod(path, mode) < 0)) {
814
virReportSystemError(errno,
815
_("cannot set mode of '%s' to %04o"),
829
959
* @gid: gid that should own file
830
960
* @flags: bit-wise or of VIR_FILE_OPEN_* flags
832
* Open @path, and execute an optional callback @hook on the open file
833
* description. @hook must return 0 on success, or -errno on failure.
834
* If @flags includes VIR_FILE_OPEN_AS_UID, then open the file while the
835
* effective user id is @uid (by using a child process); this allows
836
* one to bypass root-squashing NFS issues. If @flags includes
837
* VIR_FILE_OPEN_FORCE_PERMS, then ensure that @path has those
838
* permissions before the callback, even if the file already existed
839
* with different permissions. The return value (if non-negative)
840
* is the file descriptor, left open. Return -errno on failure. */
962
* Open @path, and return an fd to the open file. @openflags contains
963
* the flags normally passed to open(2), while those in @flags are
964
* used internally. If @flags includes VIR_FILE_OPEN_NOFORK, then try
965
* opening the file while executing with the current uid:gid
966
* (i.e. don't fork+setuid+setgid before the call to open()). If
967
* @flags includes VIR_FILE_OPEN_FORK, then try opening the file while
968
* the effective user id is @uid (by forking a child process); this
969
* allows one to bypass root-squashing NFS issues; NOFORK is always
970
* tried before FORK (the absence of both flags is treated identically
971
* to (VIR_FILE_OPEN_NOFORK | VIR_FILE_OPEN_FORK)). If @flags includes
972
* VIR_FILE_OPEN_FORCE_OWNER, then ensure that @path is owned by
973
* uid:gid before returning (even if it already existed with a
974
* different owner). If @flags includes VIR_FILE_OPEN_FORCE_MODE,
975
* ensure it has those permissions before returning (again, even if
976
* the file already existed with different permissions). The return
977
* value (if non-negative) is the file descriptor, left open. Returns
978
* -errno on failure. */
842
980
virFileOpenAs(const char *path, int openflags, mode_t mode,
843
981
uid_t uid, gid_t gid, unsigned int flags)
846
int waitret, status, ret = 0;
848
int pair[2] = { -1, -1 };
851
if ((!(flags & VIR_FILE_OPEN_AS_UID))
983
int ret = 0, fd = -1;
985
/* allow using -1 to mean "current value" */
986
if (uid == (uid_t) -1)
988
if (gid == (gid_t) -1)
991
/* treat absence of both flags as presence of both for simpler
993
if (!(flags & (VIR_FILE_OPEN_NOFORK|VIR_FILE_OPEN_FORK)))
994
flags |= VIR_FILE_OPEN_NOFORK|VIR_FILE_OPEN_FORK;
996
if ((flags & VIR_FILE_OPEN_NOFORK)
852
997
|| (getuid() != 0)
853
998
|| ((uid == 0) && (gid == 0))) {
854
flags &= ~VIR_FILE_OPEN_AS_UID;
855
return virFileOpenAsNoFork(path, openflags, mode, uid, gid, flags);
858
/* parent is running as root, but caller requested that the
859
* file be created as some other user and/or group). The
860
* following dance avoids problems caused by root-squashing
863
if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) < 0) {
865
virReportSystemError(errno,
866
_("failed to create socket needed for '%s'"),
871
forkRet = virFork(&pid);
878
if (pid) { /* parent */
879
VIR_FORCE_CLOSE(pair[1]);
882
ret = recvfd(pair[0], 0);
883
} while (ret < 0 && errno == EINTR);
885
if (ret < 0 && errno != EACCES) {
1000
if ((fd = open(path, openflags, mode)) < 0) {
887
VIR_FORCE_CLOSE(pair[0]);
888
while (waitpid(pid, NULL, 0) == -1 && errno == EINTR);
893
VIR_FORCE_CLOSE(pair[0]);
895
/* wait for child to complete, and retrieve its exit code */
896
while ((waitret = waitpid(pid, &status, 0) == -1)
897
&& (errno == EINTR));
900
virReportSystemError(errno,
901
_("failed to wait for child creating '%s'"),
906
if (!WIFEXITED(status) || (ret = -WEXITSTATUS(status)) == -EACCES ||
908
/* fall back to the simpler method, which works better in
911
flags &= ~VIR_FILE_OPEN_AS_UID;
912
return virFileOpenAsNoFork(path, openflags, mode, uid, gid, flags);
1003
ret = virFileOpenForceOwnerMode(path, fd, mode, uid, gid, flags);
1009
/* If we either 1) didn't try opening as current user at all, or
1010
* 2) failed, and errno/virStorageFileIsSharedFS indicate we might
1011
* be successful if we try as a different uid, then try doing
1012
* fork+setuid+setgid before opening.
1014
if ((fd < 0) && (flags & VIR_FILE_OPEN_FORK)) {
1017
/* An open(2) that failed due to insufficient permissions
1018
* could return one or the other of these depending on OS
1019
* version and circumstances. Any other errno indicates a
1020
* problem that couldn't be remedied by fork+setuid
1022
if (ret != -EACCES && ret != -EPERM)
1025
/* On Linux we can also verify the FS-type of the
1026
* directory. (this is a NOP on other platforms). */
1027
switch (virStorageFileIsSharedFS(path)) {
1029
/* it was on a network share, so we'll re-try */
1032
/* failure detecting fstype */
1033
virReportSystemError(errno, _("couldn't determine fs type "
1034
"of mount containing '%s'"), path);
1038
/* file isn't on a recognized network FS */
1043
/* passed all prerequisites - retry the open w/fork+setuid */
1044
if ((fd = virFileOpenForked(path, openflags, mode, uid, gid, flags)) < 0) {
924
/* error encountered and logged in virFork() after the fork. */
928
VIR_FORCE_CLOSE(pair[0]);
930
/* set desired uid/gid, then attempt to create the file */
932
if (virSetUIDGID(uid, gid) < 0) {
937
ret = virFileOpenAsNoFork(path, openflags, mode, uid, gid, flags);
943
ret = sendfd(pair[1], fd);
944
} while (ret < 0 && errno == EINTR);
952
/* ret tracks -errno on failure, but exit value must be positive.
953
* If the child exits with EACCES, then the parent tries again. */
954
/* XXX This makes assumptions about errno being < 255, which is
955
* not true on Hurd. */
956
VIR_FORCE_CLOSE(pair[1]);
958
if ((ret & 0xff) != ret) {
959
VIR_WARN("unable to pass desired return value %d", ret);
1051
/* File is successfully opened */
1057
/* whoever failed the open last has already set ret = -errno */
1058
virReportSystemError(-ret, openflags & O_CREAT
1059
? _("failed to create file '%s'")
1060
: _("failed to open file '%s'"),
1063
/* some other failure after the open succeeded */
1064
VIR_FORCE_CLOSE(fd);
1069
/* return -errno on failure, or 0 on success */
1070
static int virDirCreateNoFork(const char *path, mode_t mode, uid_t uid, gid_t gid,
1071
unsigned int flags) {
1075
if ((mkdir(path, mode) < 0)
1076
&& !((errno == EEXIST) && (flags & VIR_DIR_CREATE_ALLOW_EXIST))) {
1078
virReportSystemError(errno, _("failed to create directory '%s'"),
1083
if (stat(path, &st) == -1) {
1085
virReportSystemError(errno, _("stat of '%s' failed"), path);
1088
if (((st.st_uid != uid) || (st.st_gid != gid))
1089
&& (chown(path, uid, gid) < 0)) {
1091
virReportSystemError(errno, _("cannot chown '%s' to (%u, %u)"),
1092
path, (unsigned int) uid, (unsigned int) gid);
1095
if ((flags & VIR_DIR_CREATE_FORCE_PERMS)
1096
&& (chmod(path, mode) < 0)) {
1098
virReportSystemError(errno,
1099
_("cannot set mode of '%s' to %04o"),
966
1107
/* return -errno on failure, or 0 on success */
1640
/* Scale an integer VALUE in-place by an optional case-insensitive
1641
* SUFFIX, defaulting to SCALE if suffix is NULL or empty (scale is
1642
* typically 1 or 1024). Recognized suffixes include 'b' or 'bytes',
1643
* as well as power-of-two scaling via binary abbreviations ('KiB',
1644
* 'MiB', ...) or their one-letter counterpart ('k', 'M', ...), and
1645
* power-of-ten scaling via SI abbreviations ('KB', 'MB', ...).
1646
* Ensure that the result does not exceed LIMIT. Return 0 on success,
1647
* -1 with error message raised on failure. */
1649
virScaleInteger(unsigned long long *value, const char *suffix,
1650
unsigned long long scale, unsigned long long limit)
1652
if (!suffix || !*suffix) {
1654
virUtilError(VIR_ERR_INTERNAL_ERROR,
1655
_("invalid scale %llu"), scale);
1659
} else if (STRCASEEQ(suffix, "b") || STRCASEEQ(suffix, "byte") ||
1660
STRCASEEQ(suffix, "bytes")) {
1665
if (!suffix[1] || STRCASEEQ(suffix + 1, "iB")) {
1667
} else if (c_tolower(suffix[1]) == 'b' && !suffix[2]) {
1670
virUtilError(VIR_ERR_INVALID_ARG,
1671
_("unknown suffix '%s'"), suffix);
1675
switch (c_tolower(*suffix)) {
1695
virUtilError(VIR_ERR_INVALID_ARG,
1696
_("unknown suffix '%s'"), suffix);
1701
if (*value && *value >= (limit / scale)) {
1702
virUtilError(VIR_ERR_OVERFLOW, _("value too large: %llu%s"),
1500
1711
* virSkipSpaces:
1501
1712
* @str: pointer to the char pointer used
1740
1951
return virStrncpy(dest, src, strlen(src), destbytes);
1743
/* Compare two MAC addresses, ignoring differences in case,
1744
* as well as leading zeros.
1747
virMacAddrCompare (const char *p, const char *q)
1751
while (*p == '0' && c_isxdigit (p[1]))
1753
while (*q == '0' && c_isxdigit (q[1]))
1758
if (c == 0 || d == 0)
1765
if (UCHAR_MAX <= INT_MAX)
1768
/* On machines where 'char' and 'int' are types of the same size, the
1769
difference of two 'unsigned char' values - including the sign bit -
1770
doesn't fit in an 'int'. */
1771
return (c > d ? 1 : c < d ? -1 : 0);
1776
* @str: string representation of MAC address, e.g., "0:1E:FC:E:3a:CB"
1777
* @addr: 6-byte MAC address
1779
* Parse a MAC address
1781
* Return 0 upon success, or -1 in case of error.
1784
virParseMacAddr(const char* str, unsigned char *addr)
1789
for (i = 0; i < VIR_MAC_BUFLEN; i++) {
1791
unsigned long result;
1793
/* This is solely to avoid accepting the leading
1794
* space or "+" that strtoul would otherwise accept.
1796
if (!c_isxdigit(*str))
1799
result = strtoul(str, &end_ptr, 16);
1801
if ((end_ptr - str) < 1 || 2 < (end_ptr - str) ||
1806
addr[i] = (unsigned char) result;
1808
if ((i == 5) && (*end_ptr == '\0'))
1810
if (*end_ptr != ':')
1819
void virFormatMacAddr(const unsigned char *addr,
1822
snprintf(str, VIR_MAC_STRING_BUFLEN,
1823
"%02X:%02X:%02X:%02X:%02X:%02X",
1824
addr[0], addr[1], addr[2],
1825
addr[3], addr[4], addr[5]);
1826
str[VIR_MAC_STRING_BUFLEN-1] = '\0';
1829
void virGenerateMacAddr(const unsigned char *prefix,
1830
unsigned char *addr)
1832
addr[0] = prefix[0];
1833
addr[1] = prefix[1];
1834
addr[2] = prefix[2];
1835
addr[3] = virRandom(256);
1836
addr[4] = virRandom(256);
1837
addr[5] = virRandom(256);
1841
1954
int virEnumFromString(const char *const*types,
1842
1955
unsigned int ntypes,
1843
1956
const char *type)