RFR[ 9u-dev] JDK-8075773 - jps running as root fails with 7u75, works fine with 7u72
cheleswer sahu
cheleswer.sahu at oracle.com
Mon May 18 09:59:54 UTC 2015
Hi,
I have fixed the code and tested. It's working fine. Please review the
changes.
Web review link: http://cr.openjdk.java.net/~dbuck/8075773/webrev.02/
Regards,
Cheleswer
On 5/15/2015 12:26 PM, cheleswer sahu wrote:
> Dear Dan & Dmitry,
> Thanks for pointing out the security vulnerability in the fix and for
> your precise review. I am also agree with Dmitry's fix. I will fix the
> code and resend the review request.
>
> Regards,
> Cheleswer
>
> On 5/14/2015 9:46 PM, Gerald Thornbrugh wrote:
>> Hi Dan,
>>
>> When Cheleswer and I discussed this fix my interpretation had a
>> slightly different goal:
>>
>> Prior to the initial security fix any user could execute "jps" and
>> get the user names associated
>> with other user's perf data (i.e. the call to get_user_name_slow()
>> would succeed.). My initial
>> thought was that this was a regression for all users not just "root"
>> and this goal led to this fix.
>> At the time I did not see this as a security vulnerability, your
>> review has changed my mind.
>>
>> I agree that Dmitry's fix is a more secure fix for the issue and I
>> think we should use it.
>>
>> Let me know if you have any questions.
>>
>> Thanks!
>>
>> Jerry
>>
>>> Hi,
>>> Please review the code changes for
>>> https://bugs.openjdk.java.net/browse/JDK-8075773. I have built and
>>> tested JDK9 with fix successfully. As I do not have an account for
>>> OpenJDK,
>>> David Buck will push the fix into jdk9/hs-rt/.
>>>
>>> Web review link: http://cr.openjdk.java.net/~dbuck/8075773/webrev.01/
>>>
>>> Regards,
>>> Cheleswer
>> Cheleswer,
>>
>> Sorry for the lengthy review, but since this is security related,
>> I have to be complete.
>>
>> The goal: Add a policy by-pass for the 'root' user in order to
>> fix the regression in jps(1) behavior.
>>
>> The core of this policy by-pass is the change to this function:
>>
>> 205 static bool is_statbuf_secure(struct stat *statp, int mode) {
>> 206 if (S_ISLNK(statp->st_mode) || !S_ISDIR(statp->st_mode)) {
>> 207 // The path represents a link or some non-directory file
>> type,
>> 208 // which is not what we expected. Declare it insecure.
>> 209 //
>> 210 return false;
>> 211 }
>> 212 // If the directory is going to be opened readonly, we consider
>> this as secure operation
>> 213 // we do not need to do any more checks.
>> 214 //
>> 215 if ((mode & O_ACCMODE) == O_RDONLY) {
>> 216 return true;
>> 217 }
>> 218 // We have an existing directory, check if the permissions
>> are safe.
>> 219 //
>> 220 if ((statp->st_mode & (S_IWGRP|S_IWOTH)) != 0) {
>> 221 // The directory is open for writing and could be subjected
>> 222 // to a symlink or a hard link attack. Declare it insecure.
>> 223 //
>> 224 return false;
>> 225 }
>> 226 // See if the uid of the directory matches the effective uid of
>> the process.
>> 227 //
>> 228 if (statp->st_uid != geteuid()) {
>> 229 // The directory was not created by this user, declare it
>> insecure.
>> 230 //
>> 231 return false;
>> 232 }
>> 233 return true;
>> 234 }
>>
>> Lines 212-217 are added which allows a caller that passes in O_RDONLY
>> to by-pass the security checks on lines 220-225 and 228-232. This
>> implementation is using an attribute of _how_ the data is accessed
>> to override security policy instead of an attribute of _who_ is
>> accessing the data.
>>
>> Here are the code paths that access the modified policy code:
>>
>> is_statbuf_secure() is called by:
>>
>> - is_directory_secure()
>> - is_dirfd_secure()
>>
>> is_directory_secure() is called by:
>>
>> - get_user_name_slow() with O_RDONLY
>> - make_user_tmp_dir() with O_RDWR
>> - mmap_attach_shared() with (O_RDONLY | O_NOFOLLOW)
>>
>> is_dirfd_secure() is called by:
>>
>> - open_directory_secure() with a mode parameter
>>
>> open_directory_secure() is called by:
>>
>> - open_directory_secure_cwd() with O_RDWR
>> - get_user_name_slow() with O_RDONLY
>>
>> Only the code paths that specify O_RDWR make use of
>> the new policy by-pass code so it looks like only
>>
>> - get_user_name_slow() with O_RDONLY
>> - mmap_attach_shared() with (O_RDONLY | O_NOFOLLOW)
>>
>> are interesting.
>>
>> The new security policy by-pass will allow get_user_name_slow():
>>
>> - to process directory entries in a directory that is writable
>> which makes this use subject to a symlink or hard link attack.
>> - to process directory entries in a directory that the calling
>> user does not own; the intent of the policy by-pass is to
>> allow this for the 'root' user, but this implementation
>> allows the by-pass for any user.
>>
>> It looks like the get_user_name_slow() code is written safely
>> enough such that any symlink or hard link attack should not
>> cause any issues.
>>
>> The new policy by-pass will allow any user to determine the
>> user name associated with VMs owned by another user. This is
>> a broader policy by-pass than was intended.
>>
>>
>> The new security policy by-pass will allow mmap_attach_shared():
>>
>> - to process directory entries in a directory that is writable
>> which makes this use subject to a symlink or hard link attack.
>> - to process directory entries in a directory that the calling
>> user does not own; the intent of the policy by-pass is to
>> allow this for the 'root' user, but this implementation allows
>> the by-pass for any user.
>>
>> The mmap_attach_shared() code protects itself from a symlink
>> attack by including the 'O_NOFOLLOW' flag when opening the
>> PerfData file and it protects itself from a hardlink attack by
>> checking the hard link count after opening the file. It does
>> not protect itself against being handed a corrupted file or
>> even a very large file that would cause an OOM when the VM
>> tries to map what is supposed to be a PerfData file.
>>
>> The new policy by-pass will allow any user to access the
>> PerfData file associated with VMs owned by another user. This
>> is a broader policy by-pass than was intended.
>>
>>
>> Summary:
>>
>> This implementation of the new security policy by-pass is using
>> an attribute of _how_ the data is accessed to override security
>> policy instead of an attribute of _who_ is accessing the data.
>> This allows the VM to be exposed to some of the attacks that
>> the following fix was designed to prevent:
>>
>> JDK-8050807 Better performing performance data handling
>>
>> Dmitry's response to the code review provides a solution that
>> is based on who is accessing the data and that solution or
>> one like it should be considered.
>>
>> Again, sorry for the lengthy review.
>>
>> Dan
>
More information about the serviceability-dev
mailing list