|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * HISTORY ! 27: * ! 28: * Revision 1.1.1.1 1998/09/22 21:05:34 wsanchez ! 29: * Import of Mac OS X kernel (~semeria) ! 30: * ! 31: * Revision 1.1.1.1 1998/03/07 02:25:55 wsanchez ! 32: * Import of OSF Mach kernel (~mburg) ! 33: * ! 34: * Revision 1.1.6.1 1995/01/06 19:47:19 devrcs ! 35: * mk6 CR668 - 1.3b26 merge ! 36: * new file for mk6 ! 37: * [1994/10/12 22:19:28 dwm] ! 38: * ! 39: * Revision 1.1.3.4 1994/05/13 20:10:01 tmt ! 40: * Changed three unsigned casts to natural_t. ! 41: * [1994/05/12 22:12:28 tmt] ! 42: * ! 43: * Revision 1.1.3.2 1993/11/30 18:26:24 jph ! 44: * CR10228 -- Typo in unlock(), ledger_ledger should be child_ledger. ! 45: * [1993/11/30 16:10:43 jph] ! 46: * ! 47: * Revision 1.1.3.1 1993/11/24 21:22:14 jph ! 48: * CR9801 brezak merge, ledgers, security and NMK15_COMPAT ! 49: * [1993/11/23 22:41:07 jph] ! 50: * ! 51: * Revision 1.1.1.4 1993/09/08 14:17:36 brezak ! 52: * Include <mach/ledger_server.h> for protos. ! 53: * ! 54: * Revision 1.1.1.3 1993/08/20 14:16:55 brezak ! 55: * Created. ! 56: * ! 57: * $EndLog$ ! 58: */ ! 59: ! 60: /* ! 61: * 8/13/93 ! 62: * ! 63: * This is a half-hearted attempt at providing the parts of the ! 64: * ledger facility to satisfy the ledger interfaces. ! 65: * ! 66: * This implementation basically leaves the (dysfunctional) ledgers ! 67: * unfunctional and are mearly here to satisfy the Mach spec interface ! 68: * reqirements. ! 69: */ ! 70: ! 71: #include <mach/mach_types.h> ! 72: #include <mach/message.h> ! 73: #include <kern/mach_param.h> ! 74: #include <kern/misc_protos.h> ! 75: #include <mach/port.h> ! 76: #include <kern/lock.h> ! 77: #include <kern/ipc_kobject.h> ! 78: #include <ipc/ipc_space.h> ! 79: #include <ipc/ipc_port.h> ! 80: #include <kern/host.h> ! 81: #include <kern/ledger.h> ! 82: #include <mach/ledger_server.h> ! 83: ! 84: ledger_t root_wired_ledger; ! 85: ledger_t root_paged_ledger; ! 86: ! 87: ! 88: /* Utility routine to handle entries to a ledger */ ! 89: kern_return_t ! 90: ledger_enter( ! 91: ledger_t ledger, ! 92: ledger_item_t amount) ! 93: { ! 94: /* Need to lock the ledger */ ! 95: ledger_lock(ledger); ! 96: ! 97: if (amount > 0) { ! 98: if (ledger->ledger_limit != LEDGER_ITEM_INFINITY && ! 99: ledger->ledger_balance + amount > ledger->ledger_limit) { ! 100: /* XXX this is where you do BAD things */ ! 101: printf("Ledger limit exceeded ! ledger=%x lim=%d balance=%d\n", ! 102: ledger, ledger->ledger_limit, ! 103: ledger->ledger_balance); ! 104: ledger_unlock(ledger); ! 105: return(KERN_RESOURCE_SHORTAGE); ! 106: } ! 107: if ((natural_t)(ledger->ledger_balance + amount) ! 108: < LEDGER_ITEM_INFINITY) ! 109: ledger->ledger_balance += amount; ! 110: else ! 111: ledger->ledger_balance = LEDGER_ITEM_INFINITY; ! 112: } ! 113: else if (amount) { ! 114: if (ledger->ledger_balance + amount > 0) ! 115: ledger->ledger_balance += amount; ! 116: else ! 117: ledger->ledger_balance = 0; ! 118: } ! 119: ledger_unlock(ledger); ! 120: return(KERN_SUCCESS); ! 121: } ! 122: ! 123: /* Utility routine to create a new ledger */ ! 124: static ledger_t ! 125: ledger_allocate( ! 126: ledger_item_t limit, ! 127: ledger_t ledger_ledger, ! 128: ledger_t ledger_parent) ! 129: { ! 130: ledger_t ledger; ! 131: ! 132: ledger = (ledger_t)kalloc(sizeof(ledger_data_t)); ! 133: if (ledger == LEDGER_NULL) ! 134: return(LEDGER_NULL); ! 135: ! 136: ledger->ledger_self = ipc_port_alloc_kernel(); ! 137: if (ledger->ledger_self == IP_NULL) ! 138: return(LEDGER_NULL); ! 139: ! 140: ledger_lock_init(ledger); ! 141: ledger->ledger_limit = limit; ! 142: ledger->ledger_balance = 0; ! 143: ledger->ledger_service_port = MACH_PORT_NULL; ! 144: ledger->ledger_ledger = ledger_ledger; ! 145: ledger->ledger_parent = ledger_parent; ! 146: ipc_kobject_set(ledger->ledger_self, (ipc_kobject_t)ledger, ! 147: IKOT_LEDGER); ! 148: ! 149: return(ledger); ! 150: } ! 151: ! 152: /* Utility routine to destroy a ledger */ ! 153: static void ! 154: ledger_deallocate( ! 155: ledger_t ledger) ! 156: { ! 157: /* XXX can be many send rights (copies) of this */ ! 158: ipc_port_dealloc_kernel(ledger->ledger_self); ! 159: ! 160: /* XXX release send right on service port */ ! 161: kfree((vm_offset_t)ledger, sizeof(*ledger)); ! 162: } ! 163: ! 164: ! 165: /* ! 166: * Inititalize the ledger facility ! 167: */ ! 168: void ledger_init(void) ! 169: { ! 170: /* ! 171: * Allocate the root ledgers; wired and paged. ! 172: */ ! 173: root_wired_ledger = ledger_allocate(LEDGER_ITEM_INFINITY, ! 174: LEDGER_NULL, LEDGER_NULL); ! 175: if (root_wired_ledger == LEDGER_NULL) ! 176: panic("can't allocate root (wired) ledger"); ! 177: ipc_port_make_send(root_wired_ledger->ledger_self); ! 178: ! 179: root_paged_ledger = ledger_allocate(LEDGER_ITEM_INFINITY, ! 180: LEDGER_NULL, LEDGER_NULL); ! 181: if (root_paged_ledger == LEDGER_NULL) ! 182: panic("can't allocate root (paged) ledger"); ! 183: ipc_port_make_send(root_paged_ledger->ledger_self); ! 184: } ! 185: ! 186: /* ! 187: * Create a subordinate ledger ! 188: */ ! 189: kern_return_t ledger_create( ! 190: ledger_t parent_ledger, ! 191: ledger_t ledger_ledger, ! 192: ledger_t *new_ledger, ! 193: ledger_item_t transfer) ! 194: { ! 195: if (parent_ledger == LEDGER_NULL) ! 196: return(KERN_INVALID_ARGUMENT); ! 197: ! 198: if (ledger_ledger == LEDGER_NULL) ! 199: return(KERN_INVALID_LEDGER); ! 200: ! 201: /* ! 202: * Allocate a new ledger and change the ledger_ledger for ! 203: * its space. ! 204: */ ! 205: ledger_lock(ledger_ledger); ! 206: if ((ledger_ledger->ledger_limit != LEDGER_ITEM_INFINITY) && ! 207: (ledger_ledger->ledger_balance + sizeof(ledger_data_t) > ! 208: ledger_ledger->ledger_limit)) { ! 209: ledger_unlock(ledger_ledger); ! 210: return(KERN_RESOURCE_SHORTAGE); ! 211: } ! 212: ! 213: *new_ledger = ledger_allocate(LEDGER_ITEM_INFINITY, ledger_ledger, parent_ledger); ! 214: if (*new_ledger == LEDGER_NULL) { ! 215: ledger_unlock(ledger_ledger); ! 216: return(KERN_RESOURCE_SHORTAGE); ! 217: } ! 218: ! 219: /* ! 220: * Now transfer the limit for the new ledger from the parent ! 221: */ ! 222: ledger_lock(parent_ledger); ! 223: if (parent_ledger->ledger_limit != LEDGER_ITEM_INFINITY) { ! 224: /* Would the existing balance exceed the new limit ? */ ! 225: if (parent_ledger->ledger_limit - transfer < parent_ledger->ledger_balance) { ! 226: ledger_unlock(parent_ledger); ! 227: ledger_unlock(ledger_ledger); ! 228: return(KERN_RESOURCE_SHORTAGE); ! 229: } ! 230: if (parent_ledger->ledger_limit - transfer > 0) ! 231: parent_ledger->ledger_limit -= transfer; ! 232: else ! 233: parent_ledger->ledger_limit = 0; ! 234: } ! 235: (*new_ledger)->ledger_limit = transfer; ! 236: ! 237: /* Charge the ledger against the ledger_ledger */ ! 238: ledger_ledger->ledger_balance += sizeof(ledger_data_t); ! 239: ledger_unlock(parent_ledger); ! 240: ! 241: ledger_unlock(ledger_ledger); ! 242: ! 243: return(KERN_SUCCESS); ! 244: } ! 245: ! 246: /* ! 247: * Get the remote ledger service port ! 248: */ ! 249: kern_return_t ledger_get_remote( ! 250: ledger_t ledger, ! 251: host_t host, ! 252: ledger_t *service) ! 253: { ! 254: if (ledger == LEDGER_NULL) ! 255: return(KERN_INVALID_ARGUMENT); ! 256: ! 257: if (host == HOST_NULL) ! 258: return(KERN_INVALID_ARGUMENT); ! 259: ! 260: /* XXX if host != this host, call remote host */ ! 261: ledger_lock(ledger); ! 262: *service = convert_port_to_ledger(ledger->ledger_service_port); ! 263: ledger_unlock(ledger); ! 264: ! 265: return(KERN_SUCCESS); ! 266: } ! 267: ! 268: /* ! 269: * Return the ledger limit and balance ! 270: */ ! 271: kern_return_t ledger_read( ! 272: ledger_t ledger, ! 273: ledger_item_t *balance, ! 274: ledger_item_t *limit) ! 275: { ! 276: if (ledger == LEDGER_NULL) ! 277: return(KERN_INVALID_ARGUMENT); ! 278: ! 279: ledger_lock(ledger); ! 280: *balance = ledger->ledger_balance; ! 281: *limit = ledger->ledger_limit; ! 282: ledger_unlock(ledger); ! 283: ! 284: return(KERN_SUCCESS); ! 285: } ! 286: ! 287: /* ! 288: * Sets the remote ledger service port ! 289: */ ! 290: kern_return_t ledger_set_remote( ! 291: ledger_t ledger, ! 292: ledger_t service) ! 293: { ! 294: if (ledger == LEDGER_NULL) ! 295: return(KERN_INVALID_ARGUMENT); ! 296: ! 297: /* XXX Check that service port is a port */ ! 298: ! 299: ledger_lock(ledger); ! 300: ledger->ledger_service_port = service->ledger_self; ! 301: ledger_unlock(ledger); ! 302: ! 303: return(KERN_SUCCESS); ! 304: } ! 305: ! 306: /* ! 307: * Destroy a ledger ! 308: */ ! 309: kern_return_t ledger_terminate( ! 310: ledger_t ledger) ! 311: { ! 312: if (ledger == LEDGER_NULL) ! 313: return(KERN_INVALID_ARGUMENT); ! 314: ! 315: /* You can't deallocate kernel ledgers */ ! 316: if (ledger == root_wired_ledger || ! 317: ledger == root_paged_ledger) ! 318: return(KERN_INVALID_LEDGER); ! 319: ! 320: /* Lock the ledger */ ! 321: ledger_lock(ledger); ! 322: ! 323: /* the parent ledger gets back the limit */ ! 324: ledger_lock(ledger->ledger_parent); ! 325: if (ledger->ledger_parent->ledger_limit != LEDGER_ITEM_INFINITY) { ! 326: assert((natural_t)(ledger->ledger_parent->ledger_limit + ! 327: ledger->ledger_limit) < ! 328: LEDGER_ITEM_INFINITY); ! 329: ledger->ledger_parent->ledger_limit += ledger->ledger_limit; ! 330: } ! 331: ledger_unlock(ledger->ledger_parent); ! 332: ! 333: /* ! 334: * XXX The spec says that you have to destroy all objects that ! 335: * have been created with this ledger. Nice work eh? For now ! 336: * Transfer the balance to the parent and let it worry about ! 337: * it. ! 338: */ ! 339: /* XXX the parent ledger inherits the debt ?? */ ! 340: (void) ledger_enter(ledger->ledger_parent, ledger->ledger_balance); ! 341: ! 342: /* adjust the balance of the creation ledger */ ! 343: (void) ledger_enter(ledger->ledger_ledger, -sizeof(*ledger)); ! 344: ! 345: /* delete the ledger */ ! 346: ledger_deallocate(ledger); ! 347: ! 348: return(KERN_SUCCESS); ! 349: } ! 350: ! 351: /* ! 352: * Transfer resources from a parent ledger to a child ! 353: */ ! 354: kern_return_t ledger_transfer( ! 355: ledger_t parent_ledger, ! 356: ledger_t child_ledger, ! 357: ledger_item_t transfer) ! 358: { ! 359: #define abs(v) ((v) > 0)?(v):-(v) ! 360: ! 361: ledger_t src, dest; ! 362: ledger_item_t amount = abs(transfer); ! 363: ! 364: if (parent_ledger == LEDGER_NULL) ! 365: return(KERN_INVALID_ARGUMENT); ! 366: ! 367: if (child_ledger == LEDGER_NULL) ! 368: return(KERN_INVALID_ARGUMENT); ! 369: ! 370: /* Must be different ledgers */ ! 371: if (parent_ledger == child_ledger) ! 372: return(KERN_INVALID_ARGUMENT); ! 373: ! 374: if (transfer == 0) ! 375: return(KERN_SUCCESS); ! 376: ! 377: ledger_lock(child_ledger); ! 378: ledger_lock(parent_ledger); ! 379: ! 380: /* XXX Should be the parent you created it from ?? */ ! 381: if (parent_ledger != child_ledger->ledger_parent) { ! 382: ledger_unlock(parent_ledger); ! 383: ledger_unlock(child_ledger); ! 384: return(KERN_INVALID_LEDGER); ! 385: } ! 386: ! 387: if (transfer > 0) { ! 388: dest = child_ledger; ! 389: src = parent_ledger; ! 390: } ! 391: else { ! 392: src = child_ledger; ! 393: dest = parent_ledger; ! 394: } ! 395: ! 396: if (src->ledger_limit != LEDGER_ITEM_INFINITY) { ! 397: /* Would the existing balance exceed the new limit ? */ ! 398: if (src->ledger_limit - amount < src->ledger_balance) { ! 399: ledger_unlock(parent_ledger); ! 400: ledger_unlock(child_ledger); ! 401: return(KERN_RESOURCE_SHORTAGE); ! 402: } ! 403: if (src->ledger_limit - amount > 0) ! 404: src->ledger_limit -= amount; ! 405: else ! 406: src->ledger_limit = 0; ! 407: } ! 408: ! 409: if (dest->ledger_limit != LEDGER_ITEM_INFINITY) { ! 410: if ((natural_t)(dest->ledger_limit + amount) ! 411: < LEDGER_ITEM_INFINITY) ! 412: dest->ledger_limit += amount; ! 413: else ! 414: dest->ledger_limit = (LEDGER_ITEM_INFINITY - 1); ! 415: } ! 416: ! 417: ledger_unlock(parent_ledger); ! 418: ledger_unlock(child_ledger); ! 419: ! 420: return(KERN_SUCCESS); ! 421: #undef abs ! 422: } ! 423: ! 424: /* ! 425: * Routine: convert_port_to_ledger ! 426: * Purpose: ! 427: * Convert from a port to a ledger. ! 428: * Doesn't consume the port ref; the ledger produced may be null. ! 429: * Conditions: ! 430: * Nothing locked. ! 431: */ ! 432: ! 433: ledger_t ! 434: convert_port_to_ledger( ! 435: ipc_port_t port) ! 436: { ! 437: ledger_t ledger = LEDGER_NULL; ! 438: ! 439: if (IP_VALID(port)) { ! 440: ip_lock(port); ! 441: if (ip_active(port) && ! 442: (ip_kotype(port) == IKOT_LEDGER)) ! 443: ledger = (ledger_t) port->ip_kobject; ! 444: ip_unlock(port); ! 445: } ! 446: ! 447: return ledger; ! 448: } ! 449: ! 450: /* ! 451: * Routine: convert_ledger_to_port ! 452: * Purpose: ! 453: * Convert from a ledger to a port. ! 454: * Produces a naked send right which may be invalid. ! 455: * Conditions: ! 456: * Nothing locked. ! 457: */ ! 458: ! 459: ipc_port_t ! 460: convert_ledger_to_port( ! 461: ledger_t ledger) ! 462: { ! 463: ipc_port_t port; ! 464: ! 465: port = ipc_port_make_send(ledger->ledger_self); ! 466: ! 467: return port; ! 468: } ! 469: ! 470: /* ! 471: * Copy a ledger ! 472: */ ! 473: ipc_port_t ! 474: ledger_copy( ! 475: ledger_t ledger) ! 476: { ! 477: /* XXX reference counting */ ! 478: assert(ledger); ! 479: return(ipc_port_copy_send(ledger->ledger_self)); ! 480: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.