Skip to content

Commit

Permalink
libast: robustness fixes for temporary files and streams
Browse files Browse the repository at this point in the history
From an OpenSUSE patch:
https://build.opensuse.org/package/view_file/shells/ksh/ksh93-pathtemp.dif

See src/lib/libast/man/path.3 for pathtemp()
and src/lib/libast/man/sfio.3 for sftmp()

src/lib/libast/path/pathtemp.c:
- Error check fix: add an access check wrapper function that checks
  if a path was given and if there is enough free space on the
  device, setting errno appropriately in case of trouble.

src/lib/libast/sfio/sftmp.c:
- On Linux, use the /dev/shm shared memory objects for the new
  temporary file descriptor -- that is, do not access HD or SSD but
  only the memory based tmpfs of the POSIX SHM.
  • Loading branch information
McDutchie committed Feb 2, 2021
1 parent b12be09 commit db71b3a
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 3 deletions.
40 changes: 37 additions & 3 deletions src/lib/libast/path/pathtemp.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
#include <ls.h>
#include <tv.h>
#include <tm.h>
#include <error.h>

#define ATTEMPT 10

Expand All @@ -81,7 +82,40 @@
#define TMP1 "/tmp"
#define TMP2 "/var/tmp"

#define VALID(d) (*(d)&&!eaccess(d,W_OK|X_OK))
static inline int xaccess(const char *path, int mode)
{
static size_t pgsz;
struct statvfs vfs;
int ret;

if (!pgsz)
pgsz = strtoul(astconf("PAGESIZE",NiL,NiL),NiL,0);

if (!path || !*path)
{
errno = EFAULT;
goto err;
}

do
ret = statvfs(path, &vfs);
while (ret < 0 && errno == EINTR);

if (ret < 0)
goto err;

if (vfs.f_frsize*vfs.f_bavail < pgsz)
{
errno = ENOSPC;
goto err;
}

return eaccess(path, mode);
err:
return -1;
}

#define VALID(d) (*(d)&&!xaccess(d,W_OK|X_OK))

static struct
{
Expand Down Expand Up @@ -182,7 +216,7 @@ pathtemp(char* buf, size_t len, const char* dir, const char* pfx, int* fdp)
tv.tv_nsec = 0;
else
tvgettime(&tv);
if (!(d = (char*)dir) || *d && eaccess(d, W_OK|X_OK))
if (!(d = (char*)dir) || (*d && xaccess(d, W_OK|X_OK)))
{
if (!tmp.vec)
{
Expand Down Expand Up @@ -227,7 +261,7 @@ pathtemp(char* buf, size_t len, const char* dir, const char* pfx, int* fdp)
tmp.dir = tmp.vec;
d = *tmp.dir++;
}
if (!d && (!*(d = astconf("TMP", NiL, NiL)) || eaccess(d, W_OK|X_OK)) && eaccess(d = TMP1, W_OK|X_OK) && eaccess(d = TMP2, W_OK|X_OK))
if (!d && (!*(d = astconf("TMP", NiL, NiL)) || xaccess(d, W_OK|X_OK)) && xaccess(d = TMP1, W_OK|X_OK) && xaccess(d = TMP2, W_OK|X_OK))
return 0;
}
if (!len)
Expand Down
25 changes: 25 additions & 0 deletions src/lib/libast/sfio/sftmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@
* *
***********************************************************************/
#include "sfhdr.h"
#if _PACKAGE_ast
# if defined(__linux__) && _lib_statfs
# include <sys/statfs.h>
# ifndef TMPFS_MAGIC
# define TMPFS_MAGIC 0x01021994
# endif
# endif
#endif

/* Create a temporary stream for read/write.
** The stream is originally created as a memory-resident stream.
Expand Down Expand Up @@ -207,7 +215,24 @@ Sfio_t* f;
int fd;

#if _PACKAGE_ast
# if defined(__linux__) && _lib_statfs
/*
* Use the area of POSIX shared memory objects for the new temporary file descriptor
* that is do not access HD or SSD but only the memory based tmpfs of the POSIX SHM
*/
static int doshm;
static char *shm = "/dev/shm";
if (!doshm)
{
struct statfs fs;
if (statfs(shm, &fs) < 0 || fs.f_type != TMPFS_MAGIC || eaccess(shm, W_OK|X_OK))
shm = NiL;
doshm++;
}
if(!(file = pathtemp(NiL,PATH_MAX,shm,"sf",&fd)))
# else
if(!(file = pathtemp(NiL,PATH_MAX,NiL,"sf",&fd)))
# endif
return -1;
_rmtmp(f, file);
free(file);
Expand Down

0 comments on commit db71b3a

Please sign in to comment.