Home | History | Annotate | Download | only in vold
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef ANDROID_VOLD_VOLUME_MANAGER_H
     18 #define ANDROID_VOLD_VOLUME_MANAGER_H
     19 
     20 #include <pthread.h>
     21 #include <fnmatch.h>
     22 #include <stdlib.h>
     23 
     24 #ifdef __cplusplus
     25 
     26 #include <list>
     27 #include <mutex>
     28 #include <string>
     29 #include <unordered_map>
     30 #include <unordered_set>
     31 
     32 #include <cutils/multiuser.h>
     33 #include <utils/List.h>
     34 #include <utils/Timers.h>
     35 #include <sysutils/SocketListener.h>
     36 #include <sysutils/NetlinkEvent.h>
     37 
     38 #include "Disk.h"
     39 #include "VolumeBase.h"
     40 
     41 /* The length of an MD5 hash when encoded into ASCII hex characters */
     42 #define MD5_ASCII_LENGTH_PLUS_NULL ((MD5_DIGEST_LENGTH*2)+1)
     43 
     44 typedef enum { ASEC, OBB } container_type_t;
     45 
     46 class ContainerData {
     47 public:
     48     ContainerData(char* _id, container_type_t _type)
     49             : id(_id)
     50             , type(_type)
     51     {}
     52 
     53     ~ContainerData() {
     54         if (id != NULL) {
     55             free(id);
     56             id = NULL;
     57         }
     58     }
     59 
     60     char *id;
     61     container_type_t type;
     62 };
     63 
     64 typedef android::List<ContainerData*> AsecIdCollection;
     65 
     66 class VolumeManager {
     67 public:
     68     static const char *SEC_ASECDIR_EXT;
     69     static const char *SEC_ASECDIR_INT;
     70     static const char *ASECDIR;
     71     static const char *LOOPDIR;
     72 
     73 private:
     74     static VolumeManager *sInstance;
     75 
     76     SocketListener        *mBroadcaster;
     77 
     78     AsecIdCollection      *mActiveContainers;
     79     bool                   mDebug;
     80 
     81     // for adjusting /proc/sys/vm/dirty_ratio when UMS is active
     82     int                    mUmsSharingCount;
     83     int                    mSavedDirtyRatio;
     84     int                    mUmsDirtyRatio;
     85 
     86 public:
     87     virtual ~VolumeManager();
     88 
     89     // TODO: pipe all requests through VM to avoid exposing this lock
     90     std::mutex& getLock() { return mLock; }
     91 
     92     int start();
     93     int stop();
     94 
     95     void handleBlockEvent(NetlinkEvent *evt);
     96 
     97     class DiskSource {
     98     public:
     99         DiskSource(const std::string& sysPattern, const std::string& nickname, int flags) :
    100                 mSysPattern(sysPattern), mNickname(nickname), mFlags(flags) {
    101         }
    102 
    103         bool matches(const std::string& sysPath) {
    104             return !fnmatch(mSysPattern.c_str(), sysPath.c_str(), 0);
    105         }
    106 
    107         const std::string& getNickname() { return mNickname; }
    108         int getFlags() { return mFlags; }
    109 
    110     private:
    111         std::string mSysPattern;
    112         std::string mNickname;
    113         int mFlags;
    114     };
    115 
    116     void addDiskSource(const std::shared_ptr<DiskSource>& diskSource);
    117 
    118     std::shared_ptr<android::vold::Disk> findDisk(const std::string& id);
    119     std::shared_ptr<android::vold::VolumeBase> findVolume(const std::string& id);
    120 
    121     void listVolumes(android::vold::VolumeBase::Type type, std::list<std::string>& list);
    122 
    123     nsecs_t benchmarkPrivate(const std::string& id);
    124 
    125     int forgetPartition(const std::string& partGuid);
    126 
    127     int onUserAdded(userid_t userId, int userSerialNumber);
    128     int onUserRemoved(userid_t userId);
    129     int onUserStarted(userid_t userId);
    130     int onUserStopped(userid_t userId);
    131 
    132     int setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol);
    133 
    134     int remountUid(uid_t uid, const std::string& mode);
    135 
    136     /* Reset all internal state, typically during framework boot */
    137     int reset();
    138     /* Prepare for device shutdown, safely unmounting all devices */
    139     int shutdown();
    140     /* Unmount all volumes, usually for encryption */
    141     int unmountAll();
    142 
    143     /* ASEC */
    144     int findAsec(const char *id, char *asecPath = NULL, size_t asecPathLen = 0,
    145             const char **directory = NULL) const;
    146     int createAsec(const char *id, unsigned long numSectors, const char *fstype,
    147                    const char *key, const int ownerUid, bool isExternal);
    148     int resizeAsec(const char *id, unsigned long numSectors, const char *key);
    149     int finalizeAsec(const char *id);
    150 
    151     /**
    152      * Fixes ASEC permissions on a filesystem that has owners and permissions.
    153      * This currently means EXT4-based ASEC containers.
    154      *
    155      * There is a single file that can be marked as "private" and will not have
    156      * world-readable permission. The group for that file will be set to the gid
    157      * supplied.
    158      *
    159      * Returns 0 on success.
    160      */
    161     int fixupAsecPermissions(const char *id, gid_t gid, const char* privateFilename);
    162     int destroyAsec(const char *id, bool force);
    163     int mountAsec(const char *id, const char *key, int ownerUid, bool readOnly);
    164     int unmountAsec(const char *id, bool force);
    165     int renameAsec(const char *id1, const char *id2);
    166     int getAsecMountPath(const char *id, char *buffer, int maxlen);
    167     int getAsecFilesystemPath(const char *id, char *buffer, int maxlen);
    168 
    169     /* Loopback images */
    170     int listMountedObbs(SocketClient* cli);
    171     int mountObb(const char *fileName, const char *key, int ownerUid);
    172     int unmountObb(const char *fileName, bool force);
    173     int getObbMountPath(const char *id, char *buffer, int maxlen);
    174 
    175     /* Shared between ASEC and Loopback images */
    176     int unmountLoopImage(const char *containerId, const char *loopId,
    177             const char *fileName, const char *mountPoint, bool force);
    178 
    179     int updateVirtualDisk();
    180     int setDebug(bool enable);
    181 
    182     void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
    183     SocketListener *getBroadcaster() { return mBroadcaster; }
    184 
    185     static VolumeManager *Instance();
    186 
    187     static char *asecHash(const char *id, char *buffer, size_t len);
    188 
    189     /*
    190      * Ensure that all directories along given path exist, creating parent
    191      * directories as needed.  Validates that given path is absolute and that
    192      * it contains no relative "." or ".." paths or symlinks.  Last path segment
    193      * is treated as filename and ignored, unless the path ends with "/".  Also
    194      * ensures that path belongs to a volume managed by vold.
    195      */
    196     int mkdirs(char* path);
    197 
    198 private:
    199     VolumeManager();
    200     void readInitialState();
    201     bool isMountpointMounted(const char *mp);
    202     bool isAsecInDirectory(const char *dir, const char *asec) const;
    203     bool isLegalAsecId(const char *id) const;
    204 
    205     int linkPrimary(userid_t userId);
    206 
    207     std::mutex mLock;
    208 
    209     std::list<std::shared_ptr<DiskSource>> mDiskSources;
    210     std::list<std::shared_ptr<android::vold::Disk>> mDisks;
    211 
    212     std::unordered_map<userid_t, int> mAddedUsers;
    213     std::unordered_set<userid_t> mStartedUsers;
    214 
    215     std::string mVirtualDiskPath;
    216     std::shared_ptr<android::vold::Disk> mVirtualDisk;
    217     std::shared_ptr<android::vold::VolumeBase> mInternalEmulated;
    218     std::shared_ptr<android::vold::VolumeBase> mPrimary;
    219 };
    220 
    221 extern "C" {
    222 #endif /* __cplusplus */
    223 #define UNMOUNT_NOT_MOUNTED_ERR (-2)
    224     int vold_unmountAll(void);
    225 #ifdef __cplusplus
    226 }
    227 #endif
    228 
    229 #endif
    230