charon-tkm: charon: Avoid potential TOCTOU issues when accessing/writing PID file
Same as the previous commit.
This commit is contained in:
@@ -174,15 +174,22 @@ static bool lookup_uid_gid()
|
|||||||
static bool check_pidfile()
|
static bool check_pidfile()
|
||||||
{
|
{
|
||||||
struct stat stb;
|
struct stat stb;
|
||||||
|
int fd, flags = 0;
|
||||||
|
|
||||||
if (stat(pidfile_name, &stb) == 0)
|
#ifndef WIN32
|
||||||
|
flags |= O_NOFOLLOW;
|
||||||
|
#endif
|
||||||
|
fd = open(pidfile_name, O_RDONLY | flags);
|
||||||
|
if (fd != -1)
|
||||||
{
|
{
|
||||||
pidfile = fopen(pidfile_name, "r");
|
if (fstat(fd, &stb) == 0 && S_ISREG(stb.st_mode))
|
||||||
if (pidfile)
|
|
||||||
{
|
{
|
||||||
char buf[64];
|
char buf[64];
|
||||||
pid_t pid = 0;
|
pid_t pid = 0;
|
||||||
|
|
||||||
|
pidfile = fdopen(fd, "r");
|
||||||
|
if (pidfile)
|
||||||
|
{
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
if (fread(buf, 1, sizeof(buf), pidfile))
|
if (fread(buf, 1, sizeof(buf), pidfile))
|
||||||
{
|
{
|
||||||
@@ -191,6 +198,11 @@ static bool check_pidfile()
|
|||||||
}
|
}
|
||||||
fclose(pidfile);
|
fclose(pidfile);
|
||||||
pidfile = NULL;
|
pidfile = NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
if (pid && pid != getpid() && kill(pid, 0) == 0)
|
if (pid && pid != getpid() && kill(pid, 0) == 0)
|
||||||
{
|
{
|
||||||
DBG1(DBG_DMN, "%s already running ('%s' exists)", dmn_name,
|
DBG1(DBG_DMN, "%s already running ('%s' exists)", dmn_name,
|
||||||
@@ -198,20 +210,23 @@ static bool check_pidfile()
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fd != -1 || errno != ENOENT)
|
||||||
|
{
|
||||||
DBG1(DBG_DMN, "removing pidfile '%s', process not running", pidfile_name);
|
DBG1(DBG_DMN, "removing pidfile '%s', process not running", pidfile_name);
|
||||||
unlink(pidfile_name);
|
unlink(pidfile_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create new pidfile */
|
/* create new pidfile securely without following symlinks */
|
||||||
pidfile = fopen(pidfile_name, "w");
|
fd = open(pidfile_name, O_CREAT | O_EXCL | O_WRONLY, 0644);
|
||||||
if (pidfile)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = fileno(pidfile);
|
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
{
|
{
|
||||||
DBG1(DBG_DMN, "unable to determine fd for '%s'", pidfile_name);
|
DBG1(DBG_DMN, "unable to create pidfile '%s'", pidfile_name);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
|
||||||
@@ -222,15 +237,18 @@ static bool check_pidfile()
|
|||||||
ignore_result(fchown(fd,
|
ignore_result(fchown(fd,
|
||||||
lib->caps->get_uid(lib->caps),
|
lib->caps->get_uid(lib->caps),
|
||||||
lib->caps->get_gid(lib->caps)));
|
lib->caps->get_gid(lib->caps)));
|
||||||
|
pidfile = fdopen(fd, "w");
|
||||||
|
if (!pidfile)
|
||||||
|
{
|
||||||
|
DBG1(DBG_DMN, "unable to open pidfile '%s': %s", pidfile_name,
|
||||||
|
strerror(errno));
|
||||||
|
close(fd);
|
||||||
|
unlink(pidfile_name);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
fprintf(pidfile, "%d\n", getpid());
|
fprintf(pidfile, "%d\n", getpid());
|
||||||
fflush(pidfile);
|
fflush(pidfile);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DBG1(DBG_DMN, "unable to create pidfile '%s'", pidfile_name);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user