从Java中的FileDescriptor获取路径

时间:2012-09-05 16:03:34

标签: java security permissions jsm

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

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

目前我正致力于写权限。我成功地重写了JSM的checkWrite(String filename)方法。列表中的下一个是checkWrite(FileDescriptor filedescriptor),这个证明比较棘手。由于DTE的定义方式,我需要路径信息来确定是否允许写入操作。

  • 是否可以从FileDescriptor中提取路径数据?我猜不是 - 我已经检查了文档和各种教程,我没有发现任何暗示我有任何方法可以获取这些信息(我很高兴被证明是错误的;但是让我的工作更轻松。)

  • 如果以上答案为否,是否有人建议可行的解决方法?例如,有什么方法可以编写本机代码来做我想要的并将其绑定到我的自定义JSM类中?我很喜欢这样做“先进”的东西,但我需要知道如何开始。

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

非常感谢你的时间。

3 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:0)

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

工作方式:

我们知道文件描述符包含描述符ID,用于在当前进程中定位打开的文件。

What are file descriptors, explained in simple terms?

如果我们知道描述符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其目录包含系统中运行的所有进程

     

/当前正在运行的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()本机方法的实现

SafeFileDescriptor.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

SafeFileDescriptor.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");

答案 2 :(得分:0)

希望不会受到反射限制的限制,但是现在您可以从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”(文件路径为String类型)和“ fd”(即FileDescriptor),但是两者都通过反射隐藏了