3

关于我的问题的一些快速背景:

我正在编写一个将域类型强制规范转换为 Java 安全管理器代码的编译器。简而言之,DTE 定义“类型”(对象),为这些类型分配路径;然后定义“域”(主题),并定义域对各种类型的权限(rwxdc)。我需要在 JSM 中尽可能地模拟这种行为。

目前我正在研究写权限。我已经成功覆盖了 JSM 的 checkWrite(String filename) 方法。列表中的下一个是 checkWrite(FileDescriptor filedescriptor),而这个被证明更棘手。由于 DTE 的定义方式,我需要路径信息来确定是否允许写入操作。

  • 是否可以从 FileDescriptor 中提取路径数据?我猜不是——我检查了文档和各种教程,但没有发现任何迹象表明我可以通过任何方式获取这些信息(但是,我很高兴被显示错误;那会让我的工作更轻松)。

  • 如果上述答案是否定的,有人可以提出可行的解决方法吗?例如,有什么方法可以让我编写本机代码来做我想做的事并将其绑定到我的自定义 JSM 类中?我可以做这样的“高级”事情,但我需要一些想法如何开始。

  • 还是我唯一的选择基本上是拒绝所有使用 FileDescriptor 的写权限?我非常想避免这种情况,因为这是一个糟糕的解决方案,但如果这是我需要知道的现实。

非常感谢你花时间陪伴。

4

3 回答 3

4

简短的回答是否定的,因为文件独立于用于访问该文件的路径(至少在任何重要的操作系统上)。

一种可能的解决方法是使用方面框架捕获打开文件的调用,并将引用的文件描述符放入WeakHashMap<FileDescriptor,File>. 然后,您只需在需要验证写入时查看此映射。

于 2012-09-05T17:24:38.060 回答
1

希望不会被反射限制阻止,但现在你可以使用它(代码基于另一个答案),从 Android O 开始:

val file = File(filesDir, "ff")
file.parentFile!!.mkdirs()
val fileOutputStream = FileOutputStream(file)
val fd = fileOutputStream.fd
val method = fd.javaClass.getMethod("getInt$")
val fdId = method.invoke(fd)
val path = Paths.get("/proc/self/fd/$fdId")
val filePath = Files.readSymbolicLink(path)
Log.d("AppLog", "filePath:$filePath")

虽然不确定 FileChannel。它的实现文件(“FileChannelImpl”)应该具有“path”(文件路径字符串类型)和“fd”,即 FileDescriptor,但两者都通过反射隐藏

于 2020-06-27T10:36:11.300 回答
0

java中从FileDescriptor获取路径的解决方案:

这个怎么运作:

我们知道文件描述符包含描述符 id 来定位当前进程中打开的文件。

什么是文件描述符,用简单的术语解释?

如果我们知道描述符 id,那么我们可以通过以下 java 代码轻松找到文件路径:

Path path = Paths.get("/proc/self/fd/"+fd_id);
System.out.println(Files.readSymbolicLink(path)); //return file path in file descriptor

这里:

fd_id 文件描述符 id (0,1,2 .....)

/proc 它的目录包含系统中运行的所有进程

/self 当前运行的java类进程id

/fd 文件描述符目录

//fd_id 文件描述符id

SafeFileDescriptor.java

import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Paths;
import java.nio.file.Files;
import java.nio.file.Path;  
public class SafeFileDescriptor {

 static {
    System.load("Documents/java native interface exmples/libSafeFileDescriptor.so");
}

private native int getFDid(FileDescriptor fd);

public static void main(String[] args) throws IOException{  
    FileOutputStream fout = new FileOutputStream("Documents/test.txt");
    FileDescriptor fd=fout.getFD();
    int fd_id = new SafeFileDescriptor().getFDid(fd);
    Path path = Paths.get("/proc/self/fd/"+fd_id);
    System.out.println(Files.readSymbolicLink(path));
}
}

getFDid()是用于获取给定文件描述符对象的描述符 id 的本机方法

以下代码是getFDid()本机方法的实现

安全文件描述符.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class SafeFileDescriptor */

#ifndef _Included_SafeFileDescriptor
#define _Included_SafeFileDescriptor
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     SafeFileDescriptor
 * Method:    getFDid
 * Signature: (Ljava/io/FileDescriptor;)I
 */
JNIEXPORT jint JNICALL Java_SafeFileDescriptor_getFDid
  (JNIEnv *, jobject, jobject);

#ifdef __cplusplus
}
#endif
#endif

从 java 文件 SafeFileDescriptor.java 创建 SafeFileDescriptor.h

javac -h dir SafeFileDescriptor.java

用您的目录替换“dir”以存储 SafeFileDescriptor.h

安全文件描述符.c

#include <jni.h>
#include "SafeFileDescriptor.h"

JNIEXPORT jint JNICALL Java_SafeFileDescriptor_getFDid
  (JNIEnv *env, jobject this_object, jobject fdObject) {

    jclass fileDescriptor = (*env)->GetObjectClass(env,fdObject);

    jfieldID id_fd = (*env)->GetFieldID(env, fileDescriptor, "fd", "I");

    return (*env)->GetIntField(env,fdObject,id_fd);
}

编译SafeFileDescriptor.c

gcc -fPIC -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -shared -o libSafeFileDescriptor.so SafeFileDescriptor.c

libSafeFileDescriptor.so文件添加到 java 类文件

System.load("Documents/java native interface exmples/libSafeFileDescriptor.so");
于 2019-05-14T06:19:17.760 回答