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     //TODO remove this with better solution, b/64143519
     74     static bool shutting_down;
     75 
     76 private:
     77     static VolumeManager *sInstance;
     78 
     79     SocketListener        *mBroadcaster;
     80 
     81     AsecIdCollection      *mActiveContainers;
     82     bool                   mDebug;
     83 
     84     // for adjusting /proc/sys/vm/dirty_ratio when UMS is active
     85     int                    mUmsSharingCount;
     86     int                    mSavedDirtyRatio;
     87     int                    mUmsDirtyRatio;
     88 
     89 public:
     90     virtual ~VolumeManager();
     91 
     92     // TODO: pipe all requests through VM to avoid exposing this lock
     93     std::mutex& getLock() { return mLock; }
     94 
     95     int start();
     96     int stop();
     97 
     98     void handleBlockEvent(NetlinkEvent *evt);
     99 
    100     class DiskSource {
    101     public:
    102         DiskSource(const std::string& sysPattern, const std::string& nickname, int flags) :
    103                 mSysPattern(sysPattern), mNickname(nickname), mFlags(flags) {
    104         }
    105 
    106         bool matches(const std::string& sysPath) {
    107             return !fnmatch(mSysPattern.c_str(), sysPath.c_str(), 0);
    108         }
    109 
    110         const std::string& getNickname() { return mNickname; }
    111         int getFlags() { return mFlags; }
    112 
    113     private:
    114         std::string mSysPattern;
    115         std::string mNickname;
    116         int mFlags;
    117     };
    118 
    119     void addDiskSource(const std::shared_ptr<DiskSource>& diskSource);
    120 
    121     std::shared_ptr<android::vold::Disk> findDisk(const std::string& id);
    122     std::shared_ptr<android::vold::VolumeBase> findVolume(const std::string& id);
    123 
    124     void listVolumes(android::vold::VolumeBase::Type type, std::list<std::string>& list);
    125 
    126     nsecs_t benchmarkPrivate(const std::string& id);
    127 
    128     int forgetPartition(const std::string& partGuid);
    129 
    130     int onUserAdded(userid_t userId, int userSerialNumber);
    131     int onUserRemoved(userid_t userId);
    132     int onUserStarted(userid_t userId);
    133     int onUserStopped(userid_t userId);
    134 
    135     int setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol);
    136 
    137     int remountUid(uid_t uid, const std::string& mode);
    138 
    139     /* Reset all internal state, typically during framework boot */
    140     int reset();
    141     /* Prepare for device shutdown, safely unmounting all devices */
    142     int shutdown();
    143     /* Unmount all volumes, usually for encryption */
    144     int unmountAll();
    145 
    146     /* ASEC */
    147     int findAsec(const char *id, char *asecPath = NULL, size_t asecPathLen = 0,
    148             const char **directory = NULL) const;
    149     int createAsec(const char *id, unsigned long numSectors, const char *fstype,
    150                    const char *key, const int ownerUid, bool isExternal);
    151     int resizeAsec(const char *id, unsigned long numSectors, const char *key);
    152     int finalizeAsec(const char *id);
    153 
    154     /**
    155      * Fixes ASEC permissions on a filesystem that has owners and permissions.
    156      * This currently means EXT4-based ASEC containers.
    157      *
    158      * There is a single file that can be marked as "private" and will not have
    159      * world-readable permission. The group for that file will be set to the gid
    160      * supplied.
    161      *
    162      * Returns 0 on success.
    163      */
    164     int fixupAsecPermissions(const char *id, gid_t gid, const char* privateFilename);
    165     int destroyAsec(const char *id, bool force);
    166     int mountAsec(const char *id, const char *key, int ownerUid, bool readOnly);
    167     int unmountAsec(const char *id, bool force);
    168     int renameAsec(const char *id1, const char *id2);
    169     int getAsecMountPath(const char *id, char *buffer, int maxlen);
    170     int getAsecFilesystemPath(const char *id, char *buffer, int maxlen);
    171 
    172     /* Loopback images */
    173     int listMountedObbs(SocketClient* cli);
    174     int mountObb(const char *fileName, const char *key, int ownerUid);
    175     int unmountObb(const char *fileName, bool force);
    176     int getObbMountPath(const char *id, char *buffer, int maxlen);
    177 
    178     /* Shared between ASEC and Loopback images */
    179     int unmountLoopImage(const char *containerId, const char *loopId,
    180             const char *fileName, const char *mountPoint, bool force);
    181 
    182     int updateVirtualDisk();
    183     int setDebug(bool enable);
    184 
    185     void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
    186     SocketListener *getBroadcaster() { return mBroadcaster; }
    187 
    188     static VolumeManager *Instance();
    189 
    190     static char *asecHash(const char *id, char *buffer, size_t len);
    191 
    192     /*
    193      * Ensure that all directories along given path exist, creating parent
    194      * directories as needed.  Validates that given path is absolute and that
    195      * it contains no relative "." or ".." paths or symlinks.  Last path segment
    196      * is treated as filename and ignored, unless the path ends with "/".  Also
    197      * ensures that path belongs to a volume managed by vold.
    198      */
    199     int mkdirs(char* path);
    200 
    201 private:
    202     VolumeManager();
    203     void readInitialState();
    204     bool isMountpointMounted(const char *mp);
    205     bool isAsecInDirectory(const char *dir, const char *asec) const;
    206     bool isLegalAsecId(const char *id) const;
    207 
    208     int linkPrimary(userid_t userId);
    209 
    210     std::mutex mLock;
    211 
    212     std::list<std::shared_ptr<DiskSource>> mDiskSources;
    213     std::list<std::shared_ptr<android::vold::Disk>> mDisks;
    214 
    215     std::unordered_map<userid_t, int> mAddedUsers;
    216     std::unordered_set<userid_t> mStartedUsers;
    217 
    218     std::string mVirtualDiskPath;
    219     std::shared_ptr<android::vold::Disk> mVirtualDisk;
    220     std::shared_ptr<android::vold::VolumeBase> mInternalEmulated;
    221     std::shared_ptr<android::vold::VolumeBase> mPrimary;
    222 };
    223 
    224 extern "C" {
    225 #endif /* __cplusplus */
    226 #define UNMOUNT_NOT_MOUNTED_ERR (-2)
    227     int vold_unmountAll(void);
    228 #ifdef __cplusplus
    229 }
    230 #endif
    231 
    232 #endif
    233