cifsmount: capture std{err,out} of mount.cifs to log

So it's easier to debug a failed boot.
While at it avoid closing stdin, since a printf might inject
unexpected input into a wrong place (a socket with FD 0).
Redirect stdin from /dev/null instead.

While at it improved error handling a bit (fork, waitpid can fail)

nfsmount: same here

Related: #40554
This commit is contained in:
Alexey Sheplyakov 2021-08-24 13:54:02 +04:00
parent 30a09ca772
commit a8fa5f19bf
3 changed files with 83 additions and 20 deletions

35
log.c
View File

@ -87,3 +87,38 @@ void close_log(void)
fclose(logfile);
}
}
int redirect2log(int fd)
{
int rc;
if (!logfile) {
fprintf(stderr, "%s: log file is not open", __func__);
return -1;
}
rc = dup2(fileno(logfile), fd);
if (rc < 0) {
log_message("%s: dup2 %d: error: %s", __func__, fd, strerror(errno));
}
return rc;
}
int redirect2null(int fd)
{
int nullfd = -1, newfd = -1;
nullfd = open("/dev/null", O_RDONLY);
if (nullfd < 0) {
log_message("%s: open /dev/null: %s", __func__, strerror(errno));
goto out;
}
newfd = dup2(nullfd, fd);
if (newfd < 0) {
log_message("%s: dup2: %s", __func__, strerror(errno));
goto out;
}
out:
if (nullfd >= 0) {
close(nullfd);
}
return newfd;
}

7
log.h
View File

@ -30,5 +30,12 @@ void vlog_message(const char * s, va_list args);
void log_perror(char *msg);
void open_log(void);
void close_log(void);
/* @brief Redirect given fd to log
*
* Useful to capture the output of external utilities
*/
int redirect2log(int fd);
/* @brief Redirect given fd to /dev/null */
int redirect2null(int fd);
#endif

61
mount.c
View File

@ -19,6 +19,7 @@
*
*/
#include <errno.h>
#include <stdlib.h>
#include <limits.h>
#include <unistd.h>
@ -133,13 +134,14 @@ static int nfsmount(char *dev, char *location)
{
char spec[PATH_MAX + 17], *sep;
struct sockaddr_in saddr;
int n, pid, status;
pid_t pid;
int n, status, ret = -1;
if ((sep = strchr(dev, ':'))) {
*sep = '\0';
} else {
log_message("nfsmount: directory to mount not in host:dir format");
return -1;
goto out;
}
saddr.sin_family = AF_INET;
@ -147,7 +149,7 @@ static int nfsmount(char *dev, char *location)
mygethostbyname(dev, &saddr.sin_addr)) {
log_message("nfsmount: can't get address for %s", dev);
*sep = ':';
return -1;
goto out;
}
*sep = ':';
@ -156,17 +158,26 @@ static int nfsmount(char *dev, char *location)
strncpy(spec + n, sep, sizeof(spec) - n);
log_message("nfsmount %s %s", spec, location);
if (!(pid = fork())) {
pid = fork();
if (pid < 0) {
log_message("%s: error: fork: %s", __func__, strerror(errno));
goto out;
} else if (pid == 0) {
char * argv[] = {"/bin/nfsmount", spec, location, NULL};
close(0);
close(1);
close(2);
redirect2log(STDOUT_FILENO);
redirect2log(STDERR_FILENO);
redirect2null(STDIN_FILENO);
execve(argv[0], argv, NULL);
exit(1);
} else {
if (waitpid(pid, &status, 0) < 0) {
log_message("%s: error: waitpid: %s", __func__, strerror(errno));
goto out;
}
waitpid(pid, &status, 0);
return (WIFEXITED(status) && !WEXITSTATUS(status)) ? 0 : -1;
ret = (WIFEXITED(status) && !WEXITSTATUS(status)) ? 0 : -1;
}
out:
return ret;
}
#ifdef ENABLE_CIFS
@ -174,7 +185,8 @@ static int cifsmount(char *dev, char *location)
{
char spec[PATH_MAX + 19], *sep, *ptr = dev;
struct sockaddr_in saddr;
int n, pid, status;
pid_t pid;
int n, status, ret = -1;
while (*ptr == '/') ptr++;
@ -182,7 +194,7 @@ static int cifsmount(char *dev, char *location)
*sep = '\0';
} else {
log_message("cifsmount: directory to mount not in //host/dir format");
return -1;
goto out;
}
saddr.sin_family = AF_INET;
@ -190,7 +202,7 @@ static int cifsmount(char *dev, char *location)
mygethostbyname(ptr, &saddr.sin_addr)) {
log_message("cifsmount: can't get address for %s", ptr);
*sep = '/';
return -1;
goto out;
}
*sep = '/';
@ -201,17 +213,26 @@ static int cifsmount(char *dev, char *location)
strncpy(spec + n, sep, sizeof(spec) - n);
log_message("cifsmount %s %s", spec, location);
if (!(pid = fork())) {
pid = fork();
if (pid < 0) {
log_message("%s: error: fork: %s", __func__, strerror(errno));
goto out;
} else if (pid == 0) {
char * argv[] = {"/sbin/mount.cifs", spec, location, "-oguest", NULL};
close(0);
close(1);
close(2);
redirect2log(STDOUT_FILENO);
redirect2log(STDERR_FILENO);
redirect2null(STDIN_FILENO);
execve(argv[0], argv, NULL);
exit(1);
} else {
if (waitpid(pid, &status, 0) < 0) {
log_message("%s: error: waitpid: %s", __func__, strerror(errno));
goto out;
}
waitpid(pid, &status, 0);
return (WIFEXITED(status) && !WEXITSTATUS(status)) ? 0 : -1;
ret = (WIFEXITED(status) && !WEXITSTATUS(status)) ? 0 : -1;
}
out:
return ret;
}
#endif