• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps UID - why can share file. Practical usage UID?

chihwahli

Newbie
Jan 4, 2012
13
0
Hello android masters,

Android recruit reporting.

Could someone tell me about android UID? I searched but could not find any usefull information and/or working sample prog about UID.

I programmed 2 apps:
1 to create a file on the android SD card.
2nd app reads the text from the SD card file.

additional info:
- Both app use the same android vm on my eclipse Android SDK
- package names should not matter, but I gave them different names: com.xxx and
com.yyy

The text is written to my logcat in my linux terminal. I could read the SD file created by the other app. I did not use sharedUserId. I thought that every app gets it's own UID, and that they could not share files.

Could someone tell me why I can, without setting UID?
2nd question: How is UID used practically? didn't see any sample programs that use UID.

Many thanks in advance.
 
Thanks jiminaus that is usefull info.

Is there another way to share a variable and use UID?, so that I can share data between apps. I am researching the use of UID and sharing data. Normally apps operate in different vm's. Thus totally isolated from eachother.

(I know of SQLite, etc. But that is not the research I have to do for my study. Will add that in my report as a possible way to share data between apps)

Any more volunteers who might enlighten me about UID?
 
Upvote 0
Yes, although I have read them, perhaps I missed something. Let me quote what I understand from it.

Quotes from Security and Permissions | Android Developers
Setting sharedUserId: "By doing this, for purposes of security the two packages are then treated as being the same application, with the same user ID and file permissions.... Any data stored by an application will be assigned that application's user ID, and not normally accessible to other packages"
Quote: android:sharedUserIdThe name of a Linux user ID that will be shared with other applications. By default, Android assigns each application its own unique user ID. However, if this attribute is set to the same value for two or more applications, they will all share the same ID — provided that they are also signed by the same certificate. Application with the same user ID can access each other's data and, if desired, run in the same process.How to implement: add this line to the androidManifest.xml: "android:sharedUserId="com.cwli"
My thoughts: Thus when 2 apps have the same UID, they could run in the same process


An Android app does not have permissions unless you set them in the Androidmanifest.xml file. An app can enforce their own permissions that are not found in manifest.permission.

Quotes from Android Security Overview | Android Open Source
Android application runtime: "Applications are sandboxed at kernel level..."

Filesystem permissions: "In a UNIX-style environment, filesystem permissions ensure that one user cannot alter or read another user's files. In the case of Android, each application runs as its own user. Unless the developer explicitly exposes files to other applications, files created by one application cannot be read or altered by another application." My thought: It's possible to create a file in Android filesystem and then give other apps permission to read it.
From the link Is it possible to access the SQLite-database of an Android-app on my phone? - Stack Overflow, the database is stored in "/data/data/your.applications.package/databases" This means I could let a 2nd app gain access if I set the same UID?

Did I miss some important fact and/or is my last assumption possible? (based on security perhaps
not the best way)
 
Upvote 0
Application with the same user ID can access each other's data and, if desired, run in the same process.

How to implement: add this line to the androidManifest.xml: "android:sharedUserId="com.cwli"

Yes. But the name doesn't relate to Java packages. It'll effectively become a Linux user. So I would advised against dots in the name. Perhaps, cwliappsuite or cwli_app_suite.


My thoughts: Thus when 2 apps have the same UID, they could run in the same process.

Yes.


An Android app does not have permissions unless you set them in the Androidmanifest.xml file. An app can enforce their own permissions that are not found in manifest.permission.

The security in AndroidManifest.xml is really just about filesystem and process security by way of sharing of user IDs. Manifest.permission file is about access to the features of the Android platform. I can't see a way to extend this to something like "this app by developer X can access this other app's data by developer A".


My thought: It's possible to create a file in Android filesystem and then give other apps permission to read it.

Possibly. I've not investigated this.

At the most basic, you can make a file or database world readable and/or world writable via the flags parameter of android.content.Context#openFileOutput(String, int) or android.content.Context#openOrCreateDatabase(String, int, SQLiteDatabase.CursorFactory).

If you want finer-grain control, then this could be more difficult.

On Linux, if you wanted to 2 users to be able to shared files, you'd create a Unix group and added the 2 users to that group. You'd then set the group of those files to be this new Unix group and get the file group file permission to be group readable (and writeable, if appropriate).

Again on Linux, if the filesystem support ACLs you grant and revoke permissions to files by adding ACLs.

But you can't create groups on Android and you can't can users to groups on Android. And I don't know of a way to manipulate either traditional UNIX file permissions or ACLs via the Android Java API.


From the link Is it possible to access the SQLite-database of an Android-app on my phone? - Stack Overflow, the database is stored in "/data/data/your.applications.package/databases" This means I could let a 2nd app gain access if I set the same UID?

Yes. But don't forget both apps need to signed with the same certificate.
 
Upvote 0
Tried internal storage. I have 2 sample apps:
1) Creates the internal storage, it's a variable. The same program opens this
variable and prints it's contains to logcat. (to verify it can be written /
read)
2) The 2nd app tries to read from this variable.

Remark: I did not use UID. (and every apk file gets signed with it's own UID)
Internal storage code is partly from: http://developer.android.com/guide/topics/data/datastorage.html#filesInternal

Question 1: How come I can access the variable?


I used openFileInput. Could it be that a file is created on the SD. That explains it why it could be accessed. I tried adb shell and went into a few directories, but could not find the file. Any help is appreciated!

Code:
package com.cwli;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.os.Bundle;

public class Internal_storage_create_readActivity extends Activity {
    private static final String IDS_LIST_FILE_NAME = null;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        try {
            createReadStorage();
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    public void createReadStorage() throws IOException
    {
        String FILENAME = "hello_file";
        String string = "hello from internal..storage!";

        FileOutputStream fos = null;
        try {
            fos = openFileOutput(FILENAME, Context.MODE_PRIVATE);
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        try {
            fos.write(string.getBytes());
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();            
        }
        
        try {
            fos.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
         InputStream instream = openFileInput(FILENAME);

            if (instream != null) {
                // prepare the file for reading
                InputStreamReader inputreader = new InputStreamReader(instream);
                BufferedReader buffreader = new BufferedReader(inputreader);

                String line;

                // read every line of the file into the line-variable, on line at the time
                while (( line = buffreader.readLine()) != null) {
                    System.out.println("--------------------------------");
                    System.out.println(line);
                    System.out.println("--------------------------------");
                }

              }

        
        
    }
}


Code:
package com.cwli;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import android.app.Activity;
import android.os.Bundle;

public class Internal_storage_readActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        try {
            lezen();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    
    public void lezen() throws IOException 
    {
    
    String FILENAME = "hello_file";
    InputStream instream = openFileInput(FILENAME);

    if (instream != null) 
    {
        // prepare the file for reading
        InputStreamReader inputreader = new InputStreamReader(instream);
        BufferedReader buffreader = new BufferedReader(inputreader);

        String line;

        // read every line of the file into the line-variable, on line at the time
        while (( line = buffreader.readLine()) != null) 
        {
            System.out.println("--------------------------------");
            System.out.println(line);
            System.out.println("--------------------------------");
        }

    
        
        }
    }
}
 
Upvote 0
You did ask before somewhere where the file was stored. For me, on Android 4.0.1, the file was stored in /data/data/com.cwli/files/hello_file.

How come I can access the variable? [...] Could it be that a file is created on the SD.

It can't be that came for me that the file is being created on an SD card, because my Galaxy Nexus doesn't have an SD card and all its file systems (including the "fake" /mnt/sdcard file system) support file permissions.

Yet when I run your code, it does work as you say.

However if I change the package in AndroidManifest.xml of the second app, the second app does fail with access denied.

That doesn't make sense to me. Even if two apps are in the same package, they shouldn't be able to access each others data.
 
Upvote 0
Thanks for verifying jiminaus. <thumbs up>.

I searched and found this link: Android package security - Stack Overflow

It seems I read wrongly or posts on internet about UID are not always right and contributed to my confusion. As you (jiminaus) have tested, if you change the Android packet name, you could not access the data of the other app, but if you changed both to the same packet name, you could.

Thus at this moment I guess that the same UID is given based on the same packet name. Packets with the same packet name in the AndroidManifest.xml , all get the same UID.....? Thus "all apps/apk files get a different UID, seems to be wrong perhaps...

Going to try something out....
 
Upvote 0
More info about the previous two apps.

Logcat from my create internal storage app:
I/ActivityManager( 91): Start proc com.cwli for activity com.cwli/.Internal_storage_create_readActivity: pid=643 uid=10044 gids={}
remark: The UID is 10044 and proces ID is 643

Logcat from my read app:
I/ActivityManager( 91): Start proc com.cwli for activity com.cwli/.Internal_storage_readActivity: pid=713 uid=10044 gids={}
W/NetworkManagementSocketTagger( 91): setKernelCountSet(10044, 1) failed with errno -2
I/System.out( 713): --------------------------------
I/System.out( 713): hello from internal..storage!
I/System.out( 713): --------------------------------
D/gralloc_goldfish( 713): Emulator without GPU emulation detected.
remark: As you can see the uid is 10044 with the proces ID 713

So this confirms that both apps are really running with the same UID, and thus can access eachothers data. Do notice that they have different process ID's..... As far as I know, program would not be able to access eachothers data, because they are a different process. Threads on the other hand can access eachothers data, because they share the same memory space.

Going to try:
- different package name and try to read data, check UID, if it's really different.
- What if UID is different and PID is the same. Any prog running as the same process, would be able to access eachothers data, or is Android different?
 
Upvote 0
3rd app just reads like the 2nd app, but changed the packet name from com.cwli to com.ccc. Now it looks in a different directory and the UID is different as you could see below:

I/ActivityManager( 77): Start proc com.ccc for activity com.ccc/.Internal_storage_read_different_packagenameActivity: pid=674 uid=10045 gids={}
W/NetworkManagementSocketTagger( 77): setKernelCountSet(10045, 1) failed with errno -2
D/dalvikvm( 233): GC_CONCURRENT freed 310K, 5% free 9494K/9927K, paused 3ms+5ms
W/System.err( 674): java.io.FileNotFoundException: /data/data/com.ccc/files/hello_file: open failed: ENOENT (No such file or directory)

Result: Indeed. cannot access the file. Because it's running in it's own memory space...

4th app:
- different package names
- used same sharedUserId: android:sharedUserId="com.bread"


Result: app did not install:

D/AndroidRuntime( 916): Shutting down VM
W/dalvikvm( 916): threadid=1: thread exiting with uncaught exception (group=0x409c01f8)
E/AndroidRuntime( 916): FATAL EXCEPTION: main
E/AndroidRuntime( 916): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.cwli/com.cwli.Internal_storage_create_UID1Activity}: java.lang.NullPointerException

Althought it's clear how to run apps under de same UID, the use of android:sharedUserId eludes me still. Why does it not install when I set sharedUserID?
 
Upvote 0
Process IDs (PIDs) are just a runtime number. Every process that runs get's its own ID. Every time you run an app, it will get a different PID.

But you're right that if your apps are running literally at the same time, and you see the same PID then yes they are running in the same Java virtual machine in the same memory space.

However, this is not a requirement to being able to access each other's files. The only requirement is that they have the same UID, so that the filesystem permission checks pass.


Do you also notice that you can't have multiple apps with the same package installed at the same time? I didn't notice it as first, but when I ran your second app, it replaced the first app. It looks from Android's perspective, that the second app was an some kind of upgrade or replacement to first app. This explains why the two apps got the same UID without sharedUserId.


Your third app couldn't access the file because the file didn't exist, not because access was denied. However, if you hardcoded the file path in your third app to the file created by your first app, I think your third app would be denied access.


For sharedUserId to work, both your first app and your fourth app need to have this same attribute with the same value. Don't use dots in the name. This name has nothing to do with Java packages, it's ultimately related to Linux usernames.

Remove your first app. Then install and run your first app after adding sharedUserId. Then install and run your fourth app after updating its sharedUserId to match the value of your first app's sharedUserId. Now your fourth app should run under the same UID as your first app be able to access each other's file.
 
Upvote 0

BEST TECH IN 2023

We've been tracking upcoming products and ranking the best tech since 2007. Thanks for trusting our opinion: we get rewarded through affiliate links that earn us a commission and we invite you to learn more about us.

Smartphones