Skip to content

Commit

Permalink
udev: use safer temporary filename
Browse files Browse the repository at this point in the history
If the filename of a device symlink is too long, then the temporary
filename may become invalid, and we fail to create symlink.

The function `tempfn_xxxxxx()` generates a safe temporary filename,
and if it is failed, let's try to create the symlink non-atomically.

Note, that thanks to the previous commit, now only one worker can handle
the same symlink simultaneously. Hence, the device ID based temporary
filename is not necessary.
  • Loading branch information
yuwata committed Apr 11, 2022
1 parent 4ea286f commit c3d23a8
Showing 1 changed file with 12 additions and 10 deletions.
22 changes: 12 additions & 10 deletions src/udev/udev-node.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "smack-util.h"
#include "stat-util.h"
#include "string-util.h"
#include "tmpfile-util.h"
#include "udev-node.h"
#include "user-util.h"

Expand All @@ -31,6 +32,8 @@ static int create_symlink(const char *target, const char *slink) {
assert(target);
assert(slink);

(void) unlink(slink);

r = mkdir_parents_label(slink, 0755);
if (r < 0)
return r;
Expand All @@ -43,8 +46,7 @@ static int create_symlink(const char *target, const char *slink) {
}

static int node_symlink(sd_device *dev, const char *devnode, const char *slink) {
_cleanup_free_ char *target = NULL;
const char *id, *slink_tmp;
_cleanup_free_ char *target = NULL, *slink_tmp = NULL;
struct stat st;
int r;

Expand All @@ -70,18 +72,18 @@ static int node_symlink(sd_device *dev, const char *devnode, const char *slink)
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to get relative path from '%s' to '%s': %m", slink, devnode);

r = device_get_device_id(dev, &id);
r = tempfn_xxxxxx(slink, NULL, &slink_tmp);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to get device id: %m");

slink_tmp = strjoina(slink, ".tmp-", id);
(void) unlink(slink_tmp);
log_device_debug_errno(dev, r,
"Failed to generate temporary file name for symlink '%s', "
"creating symlink non-atomically, ignoring: %m",
slink);

r = create_symlink(target, slink_tmp);
r = create_symlink(target, slink_tmp ?: slink);
if (r < 0)
return log_device_debug_errno(dev, r, "Failed to create symlink '%s' to '%s': %m", slink_tmp, target);
return log_device_debug_errno(dev, r, "Failed to create symlink '%s' to '%s': %m", slink_tmp ?: slink, target);

if (rename(slink_tmp, slink) < 0) {
if (slink_tmp && rename(slink_tmp, slink) < 0) {
r = log_device_debug_errno(dev, errno, "Failed to rename '%s' to '%s': %m", slink_tmp, slink);
(void) unlink(slink_tmp);
return r;
Expand Down

0 comments on commit c3d23a8

Please sign in to comment.