Summary: The .java_pid socket/door is always created in the
    os::get_temp_directory() which is "/tmp" on BSD, Linux and
    Solaris. On MacOS X, it can be either the "secure per-user
    temporary directory" or "/tmp".

    The .attach_pid file is created by the Java side
    createAttachFile(). That code first tries to create the
    file in the process' working directory and if that fails,
    then it attempts to create the file in tmpdir.

src/solaris/classes/sun/tools/attach/LinuxVirtualMachine.java
    lines 40-44: The new comment is right for .java_pid, but
        not quite right for .attach_pid. See createAttachFile()
        method on line 280; .attach_pid creation is first
        attempted in the Java process' current working dir
        and then in tmpdir.

src/solaris/classes/sun/tools/attach/SolarisVirtualMachine.java
    lines 41-45: The new comment is right for .java_pid, but
        not quite right for .attach_pid. See createAttachFile()
        method on line 215; .attach_pid creation is first
        attempted in the Java process' current working dir
        and then in tmpdir.

test/ProblemList.txt
    No comments.


Linux HSX gory details:

The following block of code only creates the .java_pid socket in the
directory named by os::get_temp_directory(). On Linux, that function
is hardcoded to return "/tmp".

src/os/linux/vm/attachListener_linux.cpp:

   170  // Initialization - create a listener socket and bind it to a file
   171
   172  int LinuxAttachListener::init() {
   173    char path[UNIX_PATH_MAX];          // socket file
   174    char initial_path[UNIX_PATH_MAX];  // socket file during setup
175 int listener; // listener socket (file descriptor
)
   176
   177    // register function to cleanup
   178    ::atexit(listener_cleanup);
   179
   180    int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d",
181 os::get_temp_directory(), os::current_process_id());
   182    if (n < (int)UNIX_PATH_MAX) {
   183      n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path);
   184    }
   185    if (n >= (int)UNIX_PATH_MAX) {
   186      return -1;
   187    }

This block of code checks the process' current directory for an .attach_pid
file before it checks os::get_temp_directory(). However, that check is
just to see if the attach mechanism should be started. If it does get
spoofed, there is little harm.

   464  // If the file .attach_pid<pid> exists in the working directory
   465  // or /tmp then this is the trigger to start the attach mechanism
   466  bool AttachListener::is_init_trigger() {
   467    if (init_at_startup() || is_initialized()) {
468 return false; // initialized at startup or already ini
tialized
   469    }
   470    char fn[PATH_MAX+1];
   471    sprintf(fn, ".attach_pid%d", os::current_process_id());
   472    int ret;
   473    struct stat64 st;
   474    RESTARTABLE(::stat64(fn, &st), ret);
   475    if (ret == -1) {
   476      snprintf(fn, sizeof(fn), "%s/.attach_pid%d",
   477               os::get_temp_directory(), os::current_process_id());
   478      RESTARTABLE(::stat64(fn, &st), ret);
   479    }
   480    if (ret == 0) {
   481      // simple check to avoid starting the attach mechanism when
   482      // a bogus user creates the file
   483      if (st.st_uid == geteuid()) {
   484        init();
   485        return true;
   486      }
   487    }
   488    return false;
   489  }


Solaris HSX gory details:

This code assumes both files are always in /tmp/...:

src/os/solaris/dtrace/jvm_dtrace.c

   170  #define ATTACH_FILE_PATTERN "/tmp/.attach_pid%d"
   171
   172  /* fill-in the name of attach file name in given buffer */
   173  static void fill_attach_file_name(char* path, int len, pid_t pid) {
   174      memset(path, 0, len);
   175      sprintf(path, ATTACH_FILE_PATTERN, pid);
   176  }
   177
   178  #define DOOR_FILE_PATTERN "/tmp/.java_pid%d"
   179
   180  /* open door file for the given JVM */
   181  static int open_door(pid_t pid) {
   182      char path[PATH_MAX + 1];
   183      int fd;
   184
   185      sprintf(path, DOOR_FILE_PATTERN, pid);
   186      fd = file_open(path, O_RDONLY);
   187      if (fd < 0) {
   188          set_jvm_error(JVM_ERR_CANT_OPEN_DOOR);
   189          print_debug("cannot open door file %s\n", path);
   190          return -1;
   191      }
   192      print_debug("opened door file %s\n", path);
   193      if (check_permission(path) != 0) {
   194          set_jvm_error(JVM_ERR_DOOR_FILE_PERMISSION);
   195          print_debug("check permission failed for %s\n", path);
   196          file_close(fd);
   197          fd = -1;
   198      }
   199      return fd;
   200  }
   201
   202  /* create attach file for given process */
   203  static int create_attach_file(pid_t pid) {
   204      char path[PATH_MAX + 1];
   205      int fd;
   206      fill_attach_file_name(path, sizeof(path), pid);
   207      fd = file_open(path, O_CREAT | O_RDWR);
   208      if (fd < 0) {
   209          set_jvm_error(JVM_ERR_CANT_CREATE_ATTACH_FILE);
   210          print_debug("cannot create file %s\n", path);
   211      } else {
   212          print_debug("created attach file %s\n", path);
   213      }
   214      return fd;
   215  }

The following block of code only creates the .java_pid door in the
directory named by os::get_temp_directory(). On Solaris, that function
is hardcoded to return "/tmp".

src/os/solaris/vm/attachListener_solaris.cpp

   367  // Create the door
   368  int SolarisAttachListener::create_door() {
   369    char door_path[PATH_MAX+1];
   370    char initial_path[PATH_MAX+1];
   371    int fd, res;
   372
   373    // register exit function
   374    ::atexit(listener_cleanup);
   375
   376    // create the door descriptor
   377    int dd = ::door_create(enqueue_proc, NULL, 0);
   378    if (dd < 0) {
   379      return -1;
   380    }
   381
   382    // create initial file to attach door descriptor
   383    snprintf(door_path, sizeof(door_path), "%s/.java_pid%d",
   384             os::get_temp_directory(), os::current_process_id());
385 snprintf(initial_path, sizeof(initial_path), "%s.tmp", door_path);
   386    RESTARTABLE(::creat(initial_path, S_IRUSR | S_IWUSR), fd);
   387    if (fd == -1) {
388 debug_only(warning("attempt to create %s failed", initial_path));
   389      ::door_revoke(dd);
   390      return -1;
   391    }
   392    assert(fd >= 0, "bad file descriptor");
   393    RESTARTABLE(::close(fd), res);

This block of code checks the process' current directory for an .attach_pid
file before it checks os::get_temp_directory(). However, that check is
just to see if the attach mechanism should be started. If it does get
spoofed, there is little harm.

   603  // If the file .attach_pid<pid> exists in the working directory
   604  // or /tmp then this is the trigger to start the attach mechanism
   605  bool AttachListener::is_init_trigger() {
   606    if (init_at_startup() || is_initialized()) {
607 return false; // initialized at startup or already ini
tialized
   608    }
   609    char fn[PATH_MAX+1];
   610    sprintf(fn, ".attach_pid%d", os::current_process_id());
   611    int ret;
   612    struct stat64 st;
   613    RESTARTABLE(::stat64(fn, &st), ret);
   614    if (ret == -1) {
   615      snprintf(fn, sizeof(fn), "%s/.attach_pid%d",
   616               os::get_temp_directory(), os::current_process_id());
   617      RESTARTABLE(::stat64(fn, &st), ret);
   618    }
   619    if (ret == 0) {
   620      // simple check to avoid starting the attach mechanism when
   621      // a bogus user creates the file
   622      if (st.st_uid == geteuid()) {
   623        init();
   624        return true;
   625      }
   626    }
   627    return false;
   628  }


BSD/MacOS X HSX gory details:

This code assumes both files are always in /tmp/...:

src/os/bsd/dtrace/jvm_dtrace.c

   170  #define ATTACH_FILE_PATTERN "/tmp/.attach_pid%d"
   171
   172  /* fill-in the name of attach file name in given buffer */
   173  static void fill_attach_file_name(char* path, int len, pid_t pid) {
   174      memset(path, 0, len);
   175      sprintf(path, ATTACH_FILE_PATTERN, pid);
   176  }
   177
   178  #define DOOR_FILE_PATTERN "/tmp/.java_pid%d"
   179
   180  /* open door file for the given JVM */
   181  static int open_door(pid_t pid) {
   182      char path[PATH_MAX + 1];
   183      int fd;
   184
   185      sprintf(path, DOOR_FILE_PATTERN, pid);
   186      fd = file_open(path, O_RDONLY);
   187      if (fd < 0) {
   188          set_jvm_error(JVM_ERR_CANT_OPEN_DOOR);
   189          print_debug("cannot open door file %s\n", path);
   190          return -1;
   191      }
   192      print_debug("opened door file %s\n", path);
   193      if (check_permission(path) != 0) {
   194          set_jvm_error(JVM_ERR_DOOR_FILE_PERMISSION);
   195          print_debug("check permission failed for %s\n", path);
   196          file_close(fd);
   197          fd = -1;
   198      }
   199      return fd;
   200  }
   201
   202  /* create attach file for given process */
   203  static int create_attach_file(pid_t pid) {
   204      char path[PATH_MAX + 1];
   205      int fd;
   206      fill_attach_file_name(path, sizeof(path), pid);
   207      fd = file_open(path, O_CREAT | O_RDWR);
   208      if (fd < 0) {
   209          set_jvm_error(JVM_ERR_CANT_CREATE_ATTACH_FILE);
   210          print_debug("cannot create file %s\n", path);
   211      } else {
   212          print_debug("created attach file %s\n", path);
   213      }
   214      return fd;
   215  }

The following block of code only creates the .java_pid socket in the
directory named by os::get_temp_directory(). On BSD, that function
is hardcoded to return "/tmp". On MacOS X, that function returns
the path of the "secure per-user temporary directory" if one is
configured or "/tmp" if one is not.

src/os/bsd/vm/attachListener_bsd.cpp

   170  // Initialization - create a listener socket and bind it to a file
   171
   172  int BsdAttachListener::init() {
   173    char path[UNIX_PATH_MAX];          // socket file
   174    char initial_path[UNIX_PATH_MAX];  // socket file during setup
175 int listener; // listener socket (file descriptor
)
   176
   177    // register function to cleanup
   178    ::atexit(listener_cleanup);
   179
   180    int n = snprintf(path, UNIX_PATH_MAX, "%s/.java_pid%d",
181 os::get_temp_directory(), os::current_process_id());
   182    if (n < (int)UNIX_PATH_MAX) {
   183      n = snprintf(initial_path, UNIX_PATH_MAX, "%s.tmp", path);
   184    }
   185    if (n >= (int)UNIX_PATH_MAX) {
   186      return -1;
   187    }

This block of code checks the process' current directory for an .attach_pid
file before it checks os::get_temp_directory(). However, that check is
just to see if the attach mechanism should be started. If it does get
spoofed, there is little harm.

   476  // If the file .attach_pid<pid> exists in the working directory
   477  // or /tmp then this is the trigger to start the attach mechanism
   478  bool AttachListener::is_init_trigger() {
   479    if (init_at_startup() || is_initialized()) {
480 return false; // initialized at startup or already ini
tialized
   481    }
   482    char path[PATH_MAX + 1];
   483    int ret;
   484    struct stat st;
   485
   486    snprintf(path, PATH_MAX + 1, "%s/.attach_pid%d",
   487             os::get_temp_directory(), os::current_process_id());
   488    RESTARTABLE(::stat(path, &st), ret);
   489    if (ret == 0) {
   490      // simple check to avoid starting the attach mechanism when
   491      // a bogus user creates the file
   492      if (st.st_uid == geteuid()) {
   493        init();
   494        return true;
   495      }
   496    }
   497    return false;
   498  }



On 1/31/12 7:32 AM, Daniel D. Daugherty wrote:
Sorry, sent that last one as "reply to list" instead of "reply to all"...

I think you need to hold up on this one. I don't think the
assumption that .java_pid and .attach_pid files are always
in /tmp is a good one.

More in a little bit.

Dan

On 1/31/12 1:10 AM, Staffan Larsen wrote:
Moving "/tmp" to a static field, made it easier to write a comment explaining the rationale as well.

Updated webrev: http://cr.openjdk.java.net/~sla/7132199/webrev.02/ <http://cr.openjdk.java.net/%7Esla/7132199/webrev.02/>

Thanks,
/Staffan

On 31 jan 2012, at 01:23, David Holmes wrote:

On 31/01/2012 3:28 AM, Dmitry Samersoff wrote:
On 2012-01-30 16:28, Staffan Larsen wrote:
2. If you decide to hardcode "/tmp" please, create a global constant
for it.

I don't agree that this would make the code easier to read or maintain. I should, however, include a comment saying that the file is always in
/tmp regardless of the value of java.io.tmpdir.

Staffan: I still think changing the static field tmpdir to refer to "/tmp" is cleaner then putting "/tmp" in all the use-sites.

/tmp is common but not mandatory, especially if we speak about embedded
systems.

Dmitry: The point is that the VM will always put the file in /tmp. That's wrong but the issue here is making the management Java code match the hotspot code.

  Native code should use P_tmpdir constant from stdio.h rather than
hardcode "/tmp".

As we can't access it from java I recommend to create a global constant
somewhere to reduce possible future porting efforts.


Changing the tmpdir static would be a smaller fix, but all the cwd code
would then remain. Yes, HotSpot never writes to cwd.

I agree with Staffan, that looks for socket/door in cwd should be removed.

Ok, if it is never needed then remove it.

David

-Dmitry


Reply via email to