MemoryHeapBase::MemoryHeapBase(int fd, size_t size, uint32_t flags, uint32_t offset) : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), mDevice(0), mNeedUnmap(false), mOffset(0) { const size_t pagesize = getpagesize(); size = ((size + pagesize-1) & ~(pagesize-1)); mapfd(dup(fd), size, offset); }
void execumask(void) { int n, argc; char **argv, **oargv, *p; char *argv0; argv0 = nil; setstatus(""); oargv = mkargv(runq->argv->words); argv = oargv+1; for(argc=0; argv[argc]; argc++) ; ARGBEGIN{ default: usage: fprint(mapfd(2), "usage: umask [mode]\n"); goto out; }ARGEND if(argc > 1) goto usage; if(argc == 1){ n = strtol(argv[0], &p, 8); if(*p != 0 || p == argv[0]) goto usage; umask(n); goto out; } n = umask(0); umask(n); if(n < 0){ fprint(mapfd(2), "umask: %r\n"); goto out; } fprint(mapfd(1), "umask %03o\n", n); out: free(oargv); poplist(); flush(err); }
syscall_process_t& syscall_process_t::operator = (const syscall_process_t& p) { strcpy(pwd,p.pwd); mask = p.mask; for(std::map<int,int>::const_iterator i = p.fdmap.begin(); i != p.fdmap.end(); ++i) mapfd(i->first,i->second); return *this; }
MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags) : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), mDevice(0), mNeedUnmap(false) { int fd = open(device, O_RDWR); LOGE_IF(fd<0, "error opening %s: %s", device, strerror(errno)); if (fd >= 0) { const size_t pagesize = getpagesize(); size = ((size + pagesize-1) & ~(pagesize-1)); if (mapfd(fd, size) == NO_ERROR) { mDevice = device; } } }
MemoryHeapBase::MemoryHeapBase(size_t size, uint32_t flags, char const * name) : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), mDevice(0), mNeedUnmap(false), mOffset(0) { const size_t pagesize = getpagesize(); size = ((size + pagesize-1) & ~(pagesize-1)); int fd = ashmem_create_region(name == NULL ? "MemoryHeapBase" : name, size); ALOGE_IF(fd<0, "error creating ashmem region: %s", strerror(errno)); if (fd >= 0) { if (mapfd(fd, size) == NO_ERROR) { if (flags & READ_ONLY) { ashmem_set_prot_region(fd, PROT_READ); } } } }
MemoryHeapBase::MemoryHeapBase(const char* device, size_t size, uint32_t flags) : mFD(-1), mSize(0), mBase(MAP_FAILED), mFlags(flags), mDevice(0), mNeedUnmap(false) #ifndef BINDER_COMPAT , mOffset(0) #endif { int open_flags = O_RDWR; if (flags & NO_CACHING) open_flags |= O_SYNC; int fd = open(device, open_flags); LOGE_IF(fd<0, "error opening %s: %s", device, strerror(errno)); if (fd >= 0) { const size_t pagesize = getpagesize(); size = ((size + pagesize-1) & ~(pagesize-1)); if (mapfd(fd, size) == NO_ERROR) { mDevice = device; } } }
void execulimit(void) { int fd, n, argc, sethard, setsoft, limit; int flag[256]; char **argv, **oargv, *p; char *argv0; struct rlimit rl; argv0 = nil; setstatus(""); oargv = mkargv(runq->argv->words); argv = oargv+1; for(argc=0; argv[argc]; argc++) ; memset(flag, 0, sizeof flag); ARGBEGIN{ default: if(strchr(eargs, ARGC()) == nil){ eusage(); return; } case 'S': case 'H': case 'a': flag[ARGC()] = 1; break; }ARGEND if(argc > 1){ eusage(); goto out; } fd = mapfd(1); sethard = 1; setsoft = 1; if(flag['S'] && flag['H']) ; else if(flag['S']) sethard = 0; else if(flag['H']) setsoft = 0; limit = Notset; if(argc>0){ if(strcmp(argv[0], "unlimited") == 0) limit = Unlimited; else if(strcmp(argv[0], "hard") == 0) limit = Hard; else if(strcmp(argv[0], "soft") == 0) limit = Soft; else if((limit = strtol(argv[0], &p, 0)) < 0 || *p != 0){ eusage(); goto out; } } if(flag['a']){ for(p=eargs; *p; p++){ getrlimit(rlx[p-eargs], &rl); n = flag['H'] ? rl.rlim_max : rl.rlim_cur; if(n == -1) fprint(fd, "ulimit -%c unlimited\n", *p); else fprint(fd, "ulimit -%c %d\n", *p, n); } goto out; } for(p=eargs; *p; p++){ if(flag[(uchar)*p]){ n = 0; getrlimit(rlx[p-eargs], &rl); switch(limit){ case Notset: n = flag['H'] ? rl.rlim_max : rl.rlim_cur; if(n == -1) fprint(fd, "ulimit -%c unlimited\n", *p); else fprint(fd, "ulimit -%c %d\n", *p, n); break; case Hard: n = rl.rlim_max; goto set; case Soft: n = rl.rlim_cur; goto set; case Unlimited: n = -1; goto set; default: n = limit; set: if(setsoft) rl.rlim_cur = n; if(sethard) rl.rlim_max = n; if(setrlimit(rlx[p-eargs], &rl) < 0) fprint(mapfd(2), "setrlimit: %r\n"); } } } out: free(oargv); poplist(); flush(err); }
static void eusage(void) { fprint(mapfd(2), "usage: ulimit [-SHa%s [limit]]\n", eargs); }
static int produce_block_map(const char* path, const char* map_file, const char* blk_dev, bool encrypted, int status_fd) { std::string err; if (!android::base::RemoveFileIfExists(map_file, &err)) { ALOGE("failed to remove the existing map file %s: %s", map_file, err.c_str()); return -1; } std::string tmp_map_file = std::string(map_file) + ".tmp"; unique_fd mapfd(open(tmp_map_file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)); if (!mapfd) { ALOGE("failed to open %s: %s\n", tmp_map_file.c_str(), strerror(errno)); return -1; } // Make sure we can write to the status_file. if (!android::base::WriteStringToFd("0\n", status_fd)) { ALOGE("failed to update \"%s\"\n", STATUS_FILE.c_str()); return -1; } struct stat sb; if (stat(path, &sb) != 0) { ALOGE("failed to stat %s", path); return -1; } ALOGI(" block size: %ld bytes", static_cast<long>(sb.st_blksize)); int blocks = ((sb.st_size-1) / sb.st_blksize) + 1; ALOGI(" file size: %" PRId64 " bytes, %d blocks", sb.st_size, blocks); std::vector<int> ranges; std::string s = android::base::StringPrintf("%s\n%" PRId64 " %ld\n", blk_dev, sb.st_size, static_cast<long>(sb.st_blksize)); if (!android::base::WriteStringToFd(s, mapfd.get())) { ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno)); return -1; } std::vector<std::vector<unsigned char>> buffers; if (encrypted) { buffers.resize(WINDOW_SIZE, std::vector<unsigned char>(sb.st_blksize)); } int head_block = 0; int head = 0, tail = 0; unique_fd fd(open(path, O_RDONLY)); if (!fd) { ALOGE("failed to open %s for reading: %s", path, strerror(errno)); return -1; } unique_fd wfd(-1); if (encrypted) { wfd = open(blk_dev, O_WRONLY); if (!wfd) { ALOGE("failed to open fd for writing: %s", strerror(errno)); return -1; } } off64_t pos = 0; int last_progress = 0; while (pos < sb.st_size) { // Update the status file, progress must be between [0, 99]. int progress = static_cast<int>(100 * (double(pos) / double(sb.st_size))); if (progress > last_progress) { last_progress = progress; android::base::WriteStringToFd(std::to_string(progress) + "\n", status_fd); } if ((tail+1) % WINDOW_SIZE == head) { // write out head buffer int block = head_block; if (ioctl(fd.get(), FIBMAP, &block) != 0) { ALOGE("failed to find block %d", head_block); return -1; } add_block_to_ranges(ranges, block); if (encrypted) { if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(), static_cast<off64_t>(sb.st_blksize) * block) != 0) { return -1; } } head = (head + 1) % WINDOW_SIZE; ++head_block; } // read next block to tail if (encrypted) { size_t to_read = static_cast<size_t>( std::min(static_cast<off64_t>(sb.st_blksize), sb.st_size - pos)); if (!android::base::ReadFully(fd.get(), buffers[tail].data(), to_read)) { ALOGE("failed to read: %s", strerror(errno)); return -1; } pos += to_read; } else { // If we're not encrypting; we don't need to actually read // anything, just skip pos forward as if we'd read a // block. pos += sb.st_blksize; } tail = (tail+1) % WINDOW_SIZE; } while (head != tail) { // write out head buffer int block = head_block; if (ioctl(fd.get(), FIBMAP, &block) != 0) { ALOGE("failed to find block %d", head_block); return -1; } add_block_to_ranges(ranges, block); if (encrypted) { if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd.get(), static_cast<off64_t>(sb.st_blksize) * block) != 0) { return -1; } } head = (head + 1) % WINDOW_SIZE; ++head_block; } if (!android::base::WriteStringToFd( android::base::StringPrintf("%zu\n", ranges.size() / 2), mapfd.get())) { ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno)); return -1; } for (size_t i = 0; i < ranges.size(); i += 2) { if (!android::base::WriteStringToFd( android::base::StringPrintf("%d %d\n", ranges[i], ranges[i+1]), mapfd.get())) { ALOGE("failed to write %s: %s", tmp_map_file.c_str(), strerror(errno)); return -1; } } if (fsync(mapfd.get()) == -1) { ALOGE("failed to fsync \"%s\": %s", tmp_map_file.c_str(), strerror(errno)); return -1; } if (close(mapfd.get() == -1)) { ALOGE("failed to close %s: %s", tmp_map_file.c_str(), strerror(errno)); return -1; } mapfd = -1; if (encrypted) { if (fsync(wfd.get()) == -1) { ALOGE("failed to fsync \"%s\": %s", blk_dev, strerror(errno)); return -1; } if (close(wfd.get()) == -1) { ALOGE("failed to close %s: %s", blk_dev, strerror(errno)); return -1; } wfd = -1; } if (rename(tmp_map_file.c_str(), map_file) == -1) { ALOGE("failed to rename %s to %s: %s", tmp_map_file.c_str(), map_file, strerror(errno)); return -1; } // Sync dir to make rename() result written to disk. std::string file_name = map_file; std::string dir_name = dirname(&file_name[0]); unique_fd dfd(open(dir_name.c_str(), O_RDONLY | O_DIRECTORY)); if (!dfd) { ALOGE("failed to open dir %s: %s", dir_name.c_str(), strerror(errno)); return -1; } if (fsync(dfd.get()) == -1) { ALOGE("failed to fsync %s: %s", dir_name.c_str(), strerror(errno)); return -1; } if (close(dfd.get() == -1)) { ALOGE("failed to close %s: %s", dir_name.c_str(), strerror(errno)); return -1; } dfd = -1; return 0; }
void execwhatis(void){ /* mildly wrong -- should fork before writing */ word *a, *b, *path; var *v; struct builtin *bp; char file[512]; struct io out[1]; int found, sep; a = runq->argv->words->next; if(a==0){ Xerror1("Usage: whatis name ..."); return; } setstatus(""); out->fd = mapfd(1); out->bufp = out->buf; out->ebuf = &out->buf[NBUF]; out->strp = 0; for(;a;a = a->next){ v = vlook(a->word); if(v->val){ pfmt(out, "%s=", a->word); if(v->val->next==0) pfmt(out, "%q\n", v->val->word); else{ sep='('; for(b = v->val;b && b->word;b = b->next){ pfmt(out, "%c%q", sep, b->word); sep=' '; } pfmt(out, ")\n"); } found = 1; } else found = 0; v = gvlook(a->word); if(v->fn) pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s); else{ for(bp = Builtin;bp->name;bp++) if(strcmp(a->word, bp->name)==0){ pfmt(out, "builtin %s\n", a->word); break; } if(!bp->name){ for(path = searchpath(a->word);path;path = path->next){ strcpy(file, path->word); if(file[0]) strcat(file, "/"); strcat(file, a->word); if(Executable(file)){ pfmt(out, "%s\n", file); break; } } if(!path && !found){ pfmt(err, "%s: not found\n", a->word); setstatus("not found"); } } } } poplist(); flush(err); }
static int produce_block_map(const char* path, const char* map_file, const char* blk_dev, bool encrypted, bool f2fs_fs, int socket) { std::string err; if (!android::base::RemoveFileIfExists(map_file, &err)) { LOG(ERROR) << "failed to remove the existing map file " << map_file << ": " << err; return kUncryptFileRemoveError; } std::string tmp_map_file = std::string(map_file) + ".tmp"; android::base::unique_fd mapfd(open(tmp_map_file.c_str(), O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)); if (mapfd == -1) { PLOG(ERROR) << "failed to open " << tmp_map_file; return kUncryptFileOpenError; } // Make sure we can write to the socket. if (!write_status_to_socket(0, socket)) { LOG(ERROR) << "failed to write to socket " << socket; return kUncryptSocketWriteError; } struct stat sb; if (stat(path, &sb) != 0) { LOG(ERROR) << "failed to stat " << path; return kUncryptFileStatError; } LOG(INFO) << " block size: " << sb.st_blksize << " bytes"; int blocks = ((sb.st_size-1) / sb.st_blksize) + 1; LOG(INFO) << " file size: " << sb.st_size << " bytes, " << blocks << " blocks"; std::vector<int> ranges; std::string s = android::base::StringPrintf("%s\n%" PRId64 " %" PRId64 "\n", blk_dev, static_cast<int64_t>(sb.st_size), static_cast<int64_t>(sb.st_blksize)); if (!android::base::WriteStringToFd(s, mapfd)) { PLOG(ERROR) << "failed to write " << tmp_map_file; return kUncryptWriteError; } std::vector<std::vector<unsigned char>> buffers; if (encrypted) { buffers.resize(WINDOW_SIZE, std::vector<unsigned char>(sb.st_blksize)); } int head_block = 0; int head = 0, tail = 0; android::base::unique_fd fd(open(path, O_RDONLY)); if (fd == -1) { PLOG(ERROR) << "failed to open " << path << " for reading"; return kUncryptFileOpenError; } android::base::unique_fd wfd; if (encrypted) { wfd.reset(open(blk_dev, O_WRONLY)); if (wfd == -1) { PLOG(ERROR) << "failed to open " << blk_dev << " for writing"; return kUncryptBlockOpenError; } } // F2FS-specific ioctl // It requires the below kernel commit merged in v4.16-rc1. // 1ad71a27124c ("f2fs: add an ioctl to disable GC for specific file") // In android-4.4, // 56ee1e817908 ("f2fs: updates on v4.16-rc1") // In android-4.9, // 2f17e34672a8 ("f2fs: updates on v4.16-rc1") // In android-4.14, // ce767d9a55bc ("f2fs: updates on v4.16-rc1") #ifndef F2FS_IOC_SET_PIN_FILE #ifndef F2FS_IOCTL_MAGIC #define F2FS_IOCTL_MAGIC 0xf5 #endif #define F2FS_IOC_SET_PIN_FILE _IOW(F2FS_IOCTL_MAGIC, 13, __u32) #define F2FS_IOC_GET_PIN_FILE _IOW(F2FS_IOCTL_MAGIC, 14, __u32) #endif if (f2fs_fs) { int error = ioctl(fd, F2FS_IOC_SET_PIN_FILE); // Don't break the old kernels which don't support it. if (error && errno != ENOTTY && errno != ENOTSUP) { PLOG(ERROR) << "Failed to set pin_file for f2fs: " << path << " on " << blk_dev; return kUncryptIoctlError; } } off64_t pos = 0; int last_progress = 0; while (pos < sb.st_size) { // Update the status file, progress must be between [0, 99]. int progress = static_cast<int>(100 * (double(pos) / double(sb.st_size))); if (progress > last_progress) { last_progress = progress; write_status_to_socket(progress, socket); } if ((tail+1) % WINDOW_SIZE == head) { // write out head buffer int block = head_block; if (ioctl(fd, FIBMAP, &block) != 0) { PLOG(ERROR) << "failed to find block " << head_block; return kUncryptIoctlError; } if (block == 0) { LOG(ERROR) << "failed to find block " << head_block << ", retrying"; int error = retry_fibmap(fd, path, &block, head_block); if (error != kUncryptNoError) { return error; } } add_block_to_ranges(ranges, block); if (encrypted) { if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd, static_cast<off64_t>(sb.st_blksize) * block) != 0) { return kUncryptWriteError; } } head = (head + 1) % WINDOW_SIZE; ++head_block; } // read next block to tail if (encrypted) { size_t to_read = static_cast<size_t>( std::min(static_cast<off64_t>(sb.st_blksize), sb.st_size - pos)); if (!android::base::ReadFully(fd, buffers[tail].data(), to_read)) { PLOG(ERROR) << "failed to read " << path; return kUncryptReadError; } pos += to_read; } else { // If we're not encrypting; we don't need to actually read // anything, just skip pos forward as if we'd read a // block. pos += sb.st_blksize; } tail = (tail+1) % WINDOW_SIZE; } while (head != tail) { // write out head buffer int block = head_block; if (ioctl(fd, FIBMAP, &block) != 0) { PLOG(ERROR) << "failed to find block " << head_block; return kUncryptIoctlError; } if (block == 0) { LOG(ERROR) << "failed to find block " << head_block << ", retrying"; int error = retry_fibmap(fd, path, &block, head_block); if (error != kUncryptNoError) { return error; } } add_block_to_ranges(ranges, block); if (encrypted) { if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd, static_cast<off64_t>(sb.st_blksize) * block) != 0) { return kUncryptWriteError; } } head = (head + 1) % WINDOW_SIZE; ++head_block; } if (!android::base::WriteStringToFd( android::base::StringPrintf("%zu\n", ranges.size() / 2), mapfd)) { PLOG(ERROR) << "failed to write " << tmp_map_file; return kUncryptWriteError; } for (size_t i = 0; i < ranges.size(); i += 2) { if (!android::base::WriteStringToFd( android::base::StringPrintf("%d %d\n", ranges[i], ranges[i+1]), mapfd)) { PLOG(ERROR) << "failed to write " << tmp_map_file; return kUncryptWriteError; } } if (fsync(mapfd) == -1) { PLOG(ERROR) << "failed to fsync \"" << tmp_map_file << "\""; return kUncryptFileSyncError; } if (close(mapfd.release()) == -1) { PLOG(ERROR) << "failed to close " << tmp_map_file; return kUncryptFileCloseError; } if (encrypted) { if (fsync(wfd) == -1) { PLOG(ERROR) << "failed to fsync \"" << blk_dev << "\""; return kUncryptFileSyncError; } if (close(wfd.release()) == -1) { PLOG(ERROR) << "failed to close " << blk_dev; return kUncryptFileCloseError; } } if (rename(tmp_map_file.c_str(), map_file) == -1) { PLOG(ERROR) << "failed to rename " << tmp_map_file << " to " << map_file; return kUncryptFileRenameError; } // Sync dir to make rename() result written to disk. std::string file_name = map_file; std::string dir_name = dirname(&file_name[0]); android::base::unique_fd dfd(open(dir_name.c_str(), O_RDONLY | O_DIRECTORY)); if (dfd == -1) { PLOG(ERROR) << "failed to open dir " << dir_name; return kUncryptFileOpenError; } if (fsync(dfd) == -1) { PLOG(ERROR) << "failed to fsync " << dir_name; return kUncryptFileSyncError; } if (close(dfd.release()) == -1) { PLOG(ERROR) << "failed to close " << dir_name; return kUncryptFileCloseError; } return 0; }
int readcontrolfile(struct letter *let, char *qid) { int fd; char ctrlfile[sizeof(CTRLPFX)+6+1]; char *ctrl = 0; size_t size; char *sep; char *p, *q, *end; struct address to; sprintf(ctrlfile, CTRLPFX "%.6s", qid); if ( (fd = open(ctrlfile, O_RDONLY)) != -1) { ctrl = mapfd(fd, &size); close(fd); } if (ctrl == 0) return 0; reset(let); strlcpy(let->qid, qid, sizeof let->qid); p = ctrl; end = p + size; for (p = ctrl ; (p < end) && (q = memchr(p, '\n', end-p)); p = q+1) { switch (*p) { case C_FROM: /* From: address */ if (let->from) freeaddress(let->from); if ( (let->from = calloc(1, sizeof let->from[0])) == 0 ) { syslog(LOG_ERR, "out of memory"); abort(); } if ( (let->from->full = restofline(1+p, q)) == 0) { syslog(LOG_ERR, "out of memory"); abort(); } let->from->domain = strdup(let->env->localhost); break; case C_TO: /* To: address */ memset(&to, 0, sizeof to); if ( (to.full = restofline(1+p, q)) == 0) { syslog(LOG_ERR, "out of memory"); abort(); } if ( ((sep = strchr(to.full, '|')) == 0) || (sep == to.full) ) { syslog(LOG_ERR, "Qid %s: corrupted to address <%s>", let->qid, to.full); abort(); } *sep++ = 0; to.domain = sep; if ( *to.domain == 0 ) { syslog(LOG_ERR, "Qid %s: corrupted to address <%s>", let->qid, to.full); abort(); } else if (newrecipient(&let->remote, &to, emUSER, NOBODY_UID, NOBODY_GID) == -1) abort(); free(to.full); break; case C_FLAGS: /* extra flags */ switch (p[1]) { case 'H': let->has_headers = 1; break; case 'F': let->mesgfrom = 1; break; } break; case C_HEADER: /* real headers live past here */ if (1+q < end) { let->headtext = restofline(1+q, end); let->headsize = strlen(let->headtext); } else { let->headtext = calloc(1,1); let->headsize = 0; } munmap(ctrl,size); return 1; } } munmap(ctrl, size); return 0; }