#include "cskernel.h"
#include "csprocess.h"
#include "kerneldiskrep.h"
#include <libproc.h>
#include <sys/codesign.h>
#include <sys/param.h> // MAXPATHLEN
namespace Security {
namespace CodeSigning {
ModuleNexus<KernelCode::Globals> KernelCode::globals;
KernelCode::Globals::Globals()
{
code = new KernelCode;
staticCode = new KernelStaticCode;
}
KernelCode::KernelCode()
: SecCode(NULL)
{
}
KernelStaticCode::KernelStaticCode()
: SecStaticCode(new KernelDiskRep())
{
}
SecCode *KernelCode::locateGuest(CFDictionaryRef attributes)
{
if (CFTypeRef attr = CFDictionaryGetValue(attributes, kSecGuestAttributePid)) {
if (CFDictionaryGetCount(attributes) != 1)
MacOSError::throwMe(errSecCSUnsupportedGuestAttributes); if (CFGetTypeID(attr) == CFNumberGetTypeID())
return (new ProcessCode(cfNumber<pid_t>(CFNumberRef(attr))))->retain();
MacOSError::throwMe(errSecCSInvalidAttributeValues);
} else
MacOSError::throwMe(errSecCSUnsupportedGuestAttributes);
}
SecStaticCode *KernelCode::mapGuestToStatic(SecCode *iguest)
{
if (ProcessCode *guest = dynamic_cast<ProcessCode *>(iguest)) {
char path[2 * MAXPATHLEN]; if (::proc_pidpath(guest->pid(), path, sizeof(path)))
return (new ProcessStaticCode(DiskRep::bestGuess(path)))->retain();
else
UnixError::throwMe();
}
MacOSError::throwMe(errSecCSNoSuchCode);
}
uint32_t KernelCode::getGuestStatus(SecCode *iguest)
{
if (ProcessCode *guest = dynamic_cast<ProcessCode *>(iguest)) {
uint32_t pFlags;
if (::csops(guest->pid(), CS_OPS_STATUS, &pFlags, 0) == -1) {
secdebug("kcode", "cannot get guest status of %p(%d) errno=%d",
guest, guest->pid(), errno);
switch (errno) {
case ESRCH:
MacOSError::throwMe(errSecCSNoSuchCode);
default:
UnixError::throwMe();
}
}
secdebug("kcode", "guest %p(%d) kernel status 0x%x", guest, guest->pid(), pFlags);
#if defined(USERSPACE_VALIDATION)
guest->staticCode()->validateExecutable();
#endif //USERSPACE_VALIDATION
return pFlags;
} else
MacOSError::throwMe(errSecCSNoSuchCode);
}
SecStaticCode *KernelCode::getStaticCode()
{
return globals().staticCode->retain();
}
} }