1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
  23  */
  24 
  25 #include <sys/types.h>
  26 #include <sys/errno.h>
  27 #include <sys/param.h>
  28 #include <sys/t_lock.h>
  29 #include <sys/systm.h>
  30 #include <sys/sysmacros.h>
  31 #include <sys/debug.h>
  32 #include <sys/time.h>
  33 #include <sys/cmn_err.h>
  34 #include <sys/vnode.h>
  35 #include <sys/stat.h>
  36 #include <sys/vfs.h>
  37 #include <sys/cred.h>
  38 #include <sys/kmem.h>
  39 #include <sys/atomic.h>
  40 #include <sys/policy.h>
  41 #include <sys/fs/tmp.h>
  42 #include <sys/fs/tmpnode.h>
  43 
  44 #define MODESHIFT       3
  45 
  46 int
  47 tmp_taccess(void *vtp, int mode, struct cred *cred)
  48 {
  49         struct tmpnode *tp = vtp;
  50         int shift = 0;
  51         /*
  52          * Check access based on owner, group and
  53          * public permissions in tmpnode.
  54          */
  55         if (crgetuid(cred) != tp->tn_uid) {
  56                 shift += MODESHIFT;
  57                 if (groupmember(tp->tn_gid, cred) == 0)
  58                         shift += MODESHIFT;
  59         }
  60 
  61         return (secpolicy_vnode_access2(cred, TNTOV(tp), tp->tn_uid,
  62             tp->tn_mode << shift, mode));
  63 }
  64 
  65 /*
  66  * Decide whether it is okay to remove within a sticky directory.
  67  * Two conditions need to be met:  write access to the directory
  68  * is needed.  In sticky directories, write access is not sufficient;
  69  * you can remove entries from a directory only if you own the directory,
  70  * if you are privileged, if you own the entry or if they entry is
  71  * a plain file and you have write access to that file.
  72  * Function returns 0 if remove access is granted.
  73  */
  74 
  75 int
  76 tmp_sticky_remove_access(struct tmpnode *dir, struct tmpnode *entry,
  77         struct cred *cr)
  78 {
  79         uid_t uid = crgetuid(cr);
  80 
  81         if ((dir->tn_mode & S_ISVTX) &&
  82             uid != dir->tn_uid &&
  83             uid != entry->tn_uid &&
  84             (entry->tn_type != VREG ||
  85             tmp_taccess(entry, VWRITE, cr) != 0))
  86                 return (secpolicy_vnode_remove(cr));
  87 
  88         return (0);
  89 }
  90 
  91 /*
  92  * Allocate zeroed memory if tmpfs_maxkmem has not been exceeded
  93  * or the 'musthave' flag is set.  'musthave' allocations should
  94  * always be subordinate to normal allocations so that tmpfs_maxkmem
  95  * can't be exceeded by more than a few KB.  Example: when creating
  96  * a new directory, the tmpnode is a normal allocation; if that
  97  * succeeds, the dirents for "." and ".." are 'musthave' allocations.
  98  */
  99 void *
 100 tmp_memalloc(size_t size, int musthave)
 101 {
 102         static time_t last_warning;
 103         time_t now;
 104 
 105         if (atomic_add_long_nv(&tmp_kmemspace, size) < tmpfs_maxkmem ||
 106             musthave)
 107                 return (kmem_zalloc(size, KM_SLEEP));
 108 
 109         atomic_add_long(&tmp_kmemspace, -size);
 110         now = gethrestime_sec();
 111         if (last_warning != now) {
 112                 last_warning = now;
 113                 cmn_err(CE_WARN, "tmp_memalloc: tmpfs over memory limit");
 114         }
 115         return (NULL);
 116 }
 117 
 118 void
 119 tmp_memfree(void *cp, size_t size)
 120 {
 121         kmem_free(cp, size);
 122         atomic_add_long(&tmp_kmemspace, -size);
 123 }
 124 
 125 /*
 126  * Convert a string containing a number (number of bytes) to a pgcnt_t,
 127  * containing the corresponding number of pages. On 32-bit kernels, the
 128  * maximum value encoded in 'str' is PAGESIZE * ULONG_MAX, while the value
 129  * returned in 'maxpg' is at most ULONG_MAX.
 130  *
 131  * If the number is followed by a "k" or "K", the value is converted from
 132  * kilobytes to bytes.  If it is followed by an "m" or "M" it is converted
 133  * from megabytes to bytes.  If it is not followed by a character it is
 134  * assumed to be in bytes. Multiple letter options are allowed, so for instance
 135  * '2mk' is interpreted as 2gb.
 136  *
 137  * Parse and overflow errors are detected and a non-zero number returned on
 138  * error.
 139  */
 140 
 141 int
 142 tmp_convnum(char *str, pgcnt_t *maxpg)
 143 {
 144         uint64_t num = 0, oldnum;
 145 #ifdef _LP64
 146         uint64_t max_bytes = ULONG_MAX;
 147 #else
 148         uint64_t max_bytes = PAGESIZE * (uint64_t)ULONG_MAX;
 149 #endif
 150         char *c;
 151 
 152         if (str == NULL)
 153                 return (EINVAL);
 154         c = str;
 155 
 156         /*
 157          * Convert str to number
 158          */
 159         while ((*c >= '0') && (*c <= '9')) {
 160                 oldnum = num;
 161                 num = num * 10 + (*c++ - '0');
 162                 if (oldnum > num) /* overflow */
 163                         return (EINVAL);
 164         }
 165 
 166         /*
 167          * Terminate on null
 168          */
 169         while (*c != '\0') {
 170                 switch (*c++) {
 171 
 172                 /*
 173                  * convert from kilobytes
 174                  */
 175                 case 'k':
 176                 case 'K':
 177                         if (num > max_bytes / 1024) /* will overflow */
 178                                 return (EINVAL);
 179                         num *= 1024;
 180                         break;
 181 
 182                 /*
 183                  * convert from megabytes
 184                  */
 185                 case 'm':
 186                 case 'M':
 187                         if (num > max_bytes / (1024 * 1024)) /* will overflow */
 188                                 return (EINVAL);
 189                         num *= 1024 * 1024;
 190                         break;
 191 
 192                 default:
 193                         return (EINVAL);
 194                 }
 195         }
 196 
 197         /*
 198          * Since btopr() rounds up to page granularity, this round-up can
 199          * cause an overflow only if 'num' is between (max_bytes - PAGESIZE)
 200          * and (max_bytes). In this case the resulting number is zero, which
 201          * is what we check for below.
 202          */
 203         if ((*maxpg = (pgcnt_t)btopr(num)) == 0 && num != 0)
 204                 return (EINVAL);
 205         return (0);
 206 }