重新链接匿名(未链接但打开)文件

2024-11-01 08:41:00
admin
原创
217
摘要:问题描述:在 Unix 中,可以创建匿名文件的句柄,例如,使用 creat() 创建并打开它,然后使用 unlink() 删除目录链接 - 留下一个具有 inode 和存储空间的文件,但无法重新打开它。此类文件通常用作临时文件(通常这就是 tmpfile() 返回给您的内容)。我的问题是:有没有办法将这样的文...

问题描述:

在 Unix 中,可以创建匿名文件的句柄,例如,使用 creat() 创建并打开它,然后使用 unlink() 删除目录链接 - 留下一个具有 inode 和存储空间的文件,但无法重新打开它。此类文件通常用作临时文件(通常这就是 tmpfile() 返回给您的内容)。

我的问题是:有没有办法将这样的文件重新附加到目录结构中?如果你能做到这一点,就意味着你可以实现文件写入,这样文件就会自动地、完整地出现。这符合我的整洁强迫症。;)

当研究相关的系统调用函数时,我期望找到一个名为 flink() 的 link() 版本(与 chmod()/fchmod() 进行比较),但至少在 Linux 上它不存在。

告诉我如何创建匿名文件而不在磁盘的目录结构中短暂地暴露文件名,这将获得加分。


解决方案 1:

flink()几年前,有人提交了一个针对拟议的 Linux系统调用的补丁,但是当 Linus 声明“在没有其他重大入侵的情况下,我们绝对不可能安全地做到这一点”时,这几乎结束了关于是否添加此功能的争论。

更新:从 Linux 3.11 开始,现在可以使用open()新标志创建一个没有目录条目的文件,并在使用带有标志的fdO_TMPFILE完全形成后将其链接到文件系统。linkat()`/proc/self/fd/`AT_SYMLINK_FOLLOW

手册页中提供了以下示例open()

    char path[PATH_MAX];
    fd = open("/path/to/dir", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);

    /* File I/O on 'fd'... */

    snprintf(path, PATH_MAX,  "/proc/self/fd/%d", fd);
    linkat(AT_FDCWD, path, AT_FDCWD, "/path/for/file", AT_SYMLINK_FOLLOW);

请注意,linkat()使用 删除最后一个链接后,将不允许重新附加打开的文件unlink()

解决方案 2:

感谢@mark4o 发布有关的帖子linkat(2),请参阅他的回答了解详情。

我想尝试一下,看看当尝试将匿名文件实际链接回其存储的文件系统中时实际发生了什么。(通常/tmp,例如 Firefox 正在播放的视频数据)。


从 Linux 3.16 开始,似乎仍然没有办法恢复已删除但仍然保持打开状态的文件。即使是以 root 身份,也AT_SYMLINK_FOLLOW无法AT_EMPTY_PATH恢复linkat(2)曾经有名称的已删除文件。

唯一的选择是tail -c +1 -f /proc/19044/fd/1 > data.recov,它会生成一个单独的副本,完成后您必须手动将其终止。


这是我为测试而编写的 perl 包装器。使用它strace -eopen,linkat linkat.pl - </proc/.../fd/123 newname来验证您的系统是否仍然无法取消删除打开的文件。(使用 也一样sudo)。显然,您应该在运行之前阅读在互联网上找到的代码,或者使用沙盒帐户。

#!/usr/bin/perl -w
# 2015 Peter Cordes <peter@cordes.ca>
# public domain.  If it breaks, you get to keep both pieces.  Share and enjoy

# Linux-only linkat(2) wrapper (opens "." to get a directory FD for relative paths)
if ($#ARGV != 1) {
    print "wrong number of args.  Usage:
";
    print "linkat old new        # will use AT_SYMLINK_FOLLOW
";
    print "linkat - <old  new    # to use the AT_EMPTY_PATH flag (requires root, and still doesn't re-link arbitrary files)
";
    exit(1);
}

# use POSIX qw(linkat AT_EMPTY_PATH AT_SYMLINK_FOLLOW);  #nope, not even POSIX linkat is there

require 'syscall.ph';
use Errno;
# /usr/include/linux/fcntl.h
# #define AT_SYMLINK_NOFOLLOW   0x100   /* Do not follow symbolic links.  */
# #define AT_SYMLINK_FOLLOW 0x400   /* Follow symbolic links.  */
# #define AT_EMPTY_PATH     0x1000  /* Allow empty relative pathname */
unless (defined &AT_SYMLINK_NOFOLLOW) { sub AT_SYMLINK_NOFOLLOW() { 0x0100 } }
unless (defined &AT_SYMLINK_FOLLOW  ) { sub AT_SYMLINK_FOLLOW  () { 0x0400 } }
unless (defined &AT_EMPTY_PATH      ) { sub AT_EMPTY_PATH      () { 0x1000 } }


sub my_linkat ($$$$$) {
    # tmp copies: perl doesn't know that the string args won't be modified.
    my ($oldp, $newp, $flags) = ($_[1], $_[3], $_[4]);
    return !syscall(&SYS_linkat, fileno($_[0]), $oldp, fileno($_[2]), $newp, $flags);
}

sub linkat_dotpaths ($$$) {
    open(DOTFD, ".") or die "open . $!";
    my $ret = my_linkat(DOTFD, $_[0], DOTFD, $_[1], $_[2]);
    close DOTFD;
    return $ret;
}

sub link_stdin ($) {
    my ($newp, ) = @_;
    open(DOTFD, ".") or die "open . $!";
    my $ret = my_linkat(0, "", DOTFD, $newp, &AT_EMPTY_PATH);
    close DOTFD;
    return $ret;
}

sub linkat_follow_dotpaths ($$) {
    return linkat_dotpaths($_[0], $_[1], &AT_SYMLINK_FOLLOW);
}


## main
my $oldp = $ARGV[0];
my $newp = $ARGV[1];

# link($oldp, $newp) or die "$!";
# my_linkat(fileno(DIRFD), $oldp, fileno(DIRFD), $newp, AT_SYMLINK_FOLLOW) or die "$!";

if ($oldp eq '-') {
    print "linking stdin to '$newp'.  You will get ENOENT without root (or CAP_DAC_READ_SEARCH).  Even then doesn't work when links=0
";
    $ret = link_stdin( $newp );
} else {
    $ret = linkat_follow_dotpaths($oldp, $newp);
}
# either way, you still can't re-link deleted files (tested Linux 3.16 and 4.2).

# print STDERR 
die "error: linkat: $!.
" . ($!{ENOENT} ? "ENOENT is the error you get when trying to re-link a deleted file
" : '') unless $ret;

# if you want to see exactly what happened, run
# strace -eopen,linkat  linkat.pl

解决方案 3:

我的问题是:有没有办法将这样的文件重新附加到目录结构中?如果你能做到这一点,就意味着你可以实现文件写入,这样文件就会自动地、完整地出现。这符合我的整洁强迫症。;)

如果这是您的唯一目标,您可以采用一种更简单、更广泛使用的方式实现此目标。如果您要输出到a.dat

  1. 打开a.dat.part以进行写入。

  2. 写入您的数据。

  3. 重命名a.dat.parta.dat

我可以理解想要整洁的想法,但只是为了“整洁”而取消链接文件并重新链接它有点愚蠢。

serverfault 上的这个问题似乎表明这种重新链接是不安全的并且不受支持。

解决方案 4:

显然,这是可能的——fsck例如,这样做。但是,fsck这样做会使用主要的本地化文件系统 mojo,并且显然不可移植,也无法以非特权用户身份执行。它类似于debugfs上面的评论。

编写该flink(2)调用将是一项有趣的练习。正如 ijw 指出的那样,与当前的临时文件重命名实践相比,它将提供一些优势(请注意,重命名保证是原子的)。

解决方案 5:

有点晚了,但我刚刚发现http://computer-forensics.sans.org/blog/2009/01/27/recovering-open-but-unlinked-file-data可能可以回答这个问题。不过我还没有测试过,所以 YMMV。看起来不错。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用