Can I write on my local filesystem using EFI - filesystems

I am working on this project to write files to local filesystem as soon as the OS starts through an EFI application. I need to know if it is possible. And if yes then kindly guide me a little.
Thanks

Ok, I'll give you a good heads up...
First you enumerate all FS protocols in the system.
EFI_BOOT_SERVICES* bs = ...;
EFI_GUID sfspGuid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID;
EFI_HANDLE* handles = NULL;
UINTN handleCount = 0;
efiStatus = bs->LocateHandleBuffer(ByProtocol,
&sfspGuid,
NULL,
&handleCount,
&handles);
Then you go through all of them and open the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL for each handle you found, then you can grab a device path from a handle and figure out what device it is, what partition ect. and if the drive/partition is not what you are looking for skip it and go to the next handle. Or if you don't want to mess with DP parsing it you can simply try to open your file on each partition (handle) until the operation is successful.
for (index = 0; index < (int)handleCount; ++ index)
{
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL* fs = NULL;
efiStatus = bs->HandleProtocol(
handles[index],
&sfspGuid,
(void**)&fs);
You found the handle for a partition you need. Then you open the volume.
EFI_FILE_PROTOCOL* root = NULL;
...
efiStatus = fs->OpenVolume(fs, &root);
There is some functions to enumerate files and folders ect... But if you know the correct file path you can open it right away.
EFI_FILE_PROTOCOL* token = NULL;
efiStatus = root->Open(
root,
&token,
L"myfolder\\token.bin",
EFI_FILE_MODE_READ,
EFI_FILE_READ_ONLY | EFI_FILE_HIDDEN | EFI_FILE_SYSTEM);
Under the EFI_FILE_PROTOCOL you have a whole bunch of functions to operate on files:
EFI_FILE_OPEN Open;
EFI_FILE_CLOSE Close;
EFI_FILE_DELETE Delete;
EFI_FILE_READ Read;
EFI_FILE_WRITE Write;
EFI_FILE_GET_POSITION GetPosition;
EFI_FILE_SET_POSITION SetPosition;
EFI_FILE_GET_INFO GetInfo;
EFI_FILE_SET_INFO SetInfo;
EFI_FILE_FLUSH Flush;

Related

Win32 GetSaveFileName() return is nonzero but file isnt saved?

I am currently setting up an Editor using Win32 as a challenge for myself but my Method for saving the file for some reason doesnt save the file. I checked multiple times with my resources and looked over threads on the internet but I either didnt have the problem that got solved there in the first place or it didnt help at all. Am I overseeing something here?
void SaveUserFile(HWND hwnd)
{
OPENFILENAME ofn;
char szFile[MAX_PATH] = "";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.lpstrFile = szFile;
ofn.lpstrFile[0] = '\0';
ofn.hwndOwner = hwnd;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrFilter = TEXT("Text document(*.txt*)\0*.txt\0Word 2016 document(*.docx*)\0*.docx\0All Files(*.*)\0*.*\0");
ofn.nFilterIndex = 1;
ofn.lpstrInitialDir = NULL;
ofn.lpstrFileTitle = NULL;
ofn.lpstrDefExt = "mp";
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
GetSaveFileName(&ofn);
}
GetSaveFileName does not save a file. It shows a dialog which allows the user to select a file name. If this returns successfully the program must then write the code to save the file, using the file name provided by the user which the program can read in szFile.
In new programs you should use the common item dialogs (IFileOpenDialog and IFileSaveDialog) rather than GetOpenFileName and GetSaveFileName. There are numerous reasons for this, but one of the most obvious is that you will not be limited in file name length.

Why this code can not change(lower) the integrity level of the file?

I have written the code to change the integrity level of an object(not a process)(in this case a file). As we know we start up with Medium integirty level but I want to lower it to "Low". I want to run a .txt file with low integrity instead of default medium.
I'm using a WINAPI mostly for this purpouses. So I created a .txt file to lower its integrity from medium to low.
void SetLowLabelToFile()
{
int k = 0;
// The LABEL_SECURITY_INFORMATION SDDL SACL to be set for low integrity
#define LOW_INTEGRITY_SDDL_SACL_W L"S:(ML;;NW;;;LW)"
DWORD dwErr = ERROR_SUCCESS;
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pSacl = NULL; // not allocated
BOOL fSaclPresent = FALSE;
BOOL fSaclDefaulted = FALSE;
LPCWSTR pwszFileName = L"C:\\Users\\Dan\\Documents\\testIntegrity\\hi1.txt";
if (ConvertStringSecurityDescriptorToSecurityDescriptorW(
LOW_INTEGRITY_SDDL_SACL_W, SDDL_REVISION_1, &pSD, NULL))
{
k = GetLastError();
if (GetSecurityDescriptorSacl(pSD, &fSaclPresent, &pSacl,
&fSaclDefaulted))
{
k = GetLastError();
// Note that psidOwner, psidGroup, and pDacl are
// all NULL and set the new LABEL_SECURITY_INFORMATION
dwErr = SetNamedSecurityInfoW((LPWSTR)pwszFileName,
SE_FILE_OBJECT, LABEL_SECURITY_INFORMATION,
NULL, NULL, NULL, pSacl);
k = GetLastError();
}
LocalFree(pSD);
}
}
I set up 3 GetLastErrors to get an error-code and the last one is 1008. This means that An attempt was made to reference a token that does not exist. I didn't get it because the way to the file is valid. Could anyone please help to solve the problem?
Data files don't have integrity levels. Processes have integrity levels.
You can't "run a .txt file", you run an "application" that then loads the .txt file. The "application" would have to be run at a low integrity level, not the .txt file itself.
The correct way to launch a low-integrity process from your code is to:
Have your code duplicate its current process handle using OpenProcessToken() and DuplicateTokenEx().
Use SetTokenInformation() to set the integrity level in that access token to Low.
Use CreateProcessAsUser() to create a new process using that Low integrity access token.
There is an example of this (in C#) on MSDN:
Create low-integrity process in C# (CSCreateLowIntegrityProcess)

Remove file from directory - ext-like file system implementation

I have an issue. I'm currently trying to implement an ext-ish file system. I've done the inode operations such as read and write. I've created a structure that represents both a regular file and a directory. I have a problem when trying to remove a certain file from the directory.
char
dirremove(struct dirent *dir, struct dirent *file)
{
dirent_t n = {.mode = NODDIR, .inumber = remdirnod,
.r = 0, .w = 0};
strcpy(n.nm, dir->nm);
dirent_t t;
dir->r = 0;
char r = 1;
while (!dirread(dir, &t))
{
int tt = dir->r;
dir->r = 0;
dirent_t ff[3];
filread(ff, dir, 3 * entrysiz);
dir->r = tt;
if (!strcmp(t.nm, ""))
return 1;
if (!(!strcmp(t.nm, file->nm) && !(r = 0)))
assert(!dirappend(&n, &t));
}
assert(n.w == dir->w - entrysiz);
dir->w = n.w;
dir->r = n.r;
copyinode(dir->inumber, remdirnod);
return r;
}
This is the function called from the rm command. It takes the directory object (where the file is stored) and the file object to be deleted. I know this solution is not the best in terms of speed and memory usage but I'm still a beginner in this area, so don't hate me a lot, please :).
The function is designed to do the following. It has to read all files and check if the current is the one to be deleted. If not, the file is added to a new directory (empty in the beginning) which will replace the old one at the end of the function. The "new" directory is an entry saved entirely for this purpose, so there isn't a chance that all inodes are already used.
The test that I've done is to create a file (works fine), then remove it, then create it again and remove it. Everything works perfectly except for the second execution of the dirremove function. The directory has its dot and dot-dot directories by default so it goes through them first. The result is that the first deletion is successful. Everything works perfectly. But the second time things go wrong somewhere.
int tt = dir->r;
dir->r = 0;
dirent_t ff[3];
filread(ff, dir, 3 * entrysize;
dir->r = tt;
I added the ff array that should read the whole content of the directory and this would help me figure out if the correct files are there. On the first and second iteration, all files (".", ".." and "some-other-file") are there but at the iteration which should hold the object of the file that's to be removed the third file suddenly goes all zeroes.
I've debugged this for several hours but it continues to fail the same way.
Probably I didn't explain the failure the best way, but there are a lot of things that I forgot to say, so if I missed something please don't ignore the question and just ask about it.

Restore or remove the Linux Kernel Module from sysfs

I recently coded a LKM which has the ability to hide itself. All works just fine when I hide the module but when I restore it and look at it in the lsmod the value of the Used By column suddenly is -2
Module Size Used by
my_module 13324 -2
vboxsf 43798 1
dm_crypt 23177 0
nfsd 284396 2
auth_rpcgss 59309 1 nfsd
nfs_acl 12837 1 nfsd
nfs 240815 0
and when I remove it i get the error saying rmmod: ERROR: Module my_module is builtin. I know that it is a refcount for the kobject associated with the module and the module can only be removed when it is 0. I am almost certain that it happens because when I hide the module I delete all of its files in the /sys/modules.(holders, parameters, sections, srcversion etc.). Can someone help me with the remove operation or restore the files back?(I don't get any errors in the dmesg)
Here is the code:
`
void module_hide(void) {
if(module_hidden) //is hidden
return;
module_prev = THIS_MODULE->list.prev;
kobject_prev = &THIS_MODULE->mkobj.kobj;
kobject_parent_prev = THIS_MODULE->mkobj.kobj.parent;
sect_attrs_bkp = THIS_MODULE->sect_attrs;
notes_attrs_bkp = THIS_MODULE->notes_attrs;
list_del(&THIS_MODULE->list); //remove from procfs
//kobject_del(THIS_MODULE->holders_dir);
kobject_del(&THIS_MODULE->mkobj.kobj); //remove from sysfs
THIS_MODULE->sect_attrs = NULL;
THIS_MODULE->notes_attrs = NULL;
module_hidden = (unsigned int)0x1;
}
void module_show(void) {
int result, result2;
if(!module_hidden) //is not hidden
return;
list_add(&THIS_MODULE->list, module_prev); //add to procfs
result = kobject_add(&THIS_MODULE->mkobj.kobj, kobject_parent_prev, "my_module"); //add the module to sysfs
if(result<0) {
printk(KERN_ALERT "Error to restore the old kobject\n");
}
result2 = kobject_add(THIS_MODULE->holders_dir, &THIS_MODULE->mkobj.kobj, "holders"); //add the holders dir to the module folder
if(!THIS_MODULE->holders_dir) {
printk(KERN_ALERT "Error to restore the old holders_dir\n");
}
THIS_MODULE->sect_attrs = sect_attrs_bkp;
THIS_MODULE->notes_attrs = notes_attrs_bkp;
//kobject_get(&THIS_MODULE->mkobj.kobj);
//tried using THIS_MODULE->refcnt = 0; and kobject_get(&THIS_MODULE->mkobj.kob) with no luck
module_hidden = (unsigned int)0x0;
}
Thanks
Using kobject_add will only add the directory as you already know, while using kobject_dell will remove the direcotry and all subdirectories.
Hence as you mention you need to add all of the subdires needed.
To understand what is the way of adding the subdirs, you read the source code of sys_init_module carefully at module.c or read kobject_del->sys_remove_dir
which remove all attributes(files) and subdirs when clear recursively kobj->kernfs_nodes.
Thus, you need create the struct recursivly with all his attrs using the functions
sysfs_add_file_mode_ns
sysfs_create_dir_ns
or:
__kernfs_create_file
kernfs_create_empty_dir
for example to add the sections file use the follwoing line:
sysfs_create_group(&THIS_MODULE->mkobj.kobj, &sect_attrs_bkp->grp))
You need you change more values in order to fix the problem but to restore the directories this will be enough.
But other solution and perherp easier one would be just to make you module directory unvisible by hijacking getdents_t and getdents64_t as done at Diamorphine.
I solved it
static void populate_sysfs(void)
{
int i;
THIS_MODULE->holders_dir=kobject_create_and_add("holders",&THIS_MODULE->mkobj.kobj);
for (i=0;(THIS_MODULE->modinfo_attrs[i].attr.name) != NULL;i++){
if (sysfs_create_file(&THIS_MODULE->mkobj.kobj,&THIS_MODULE->modinfo_attrs[i].attr)!=0)
break;
}
}

How to get mounted drive's volume name in linux using C?

I'm currently working on program, which must display information about mounted flash drive. I want to display full space, free space, file system type and volume name. But problem is that, i can't find any API through which i can get volume name(volume label). Is there any api to do this?
p.s. full space, free space and file system type i'm getting via statfs function
Assuming that you work on a recent desktop-like distribution (Fedora, Ubuntu, etc.), you have HAL daemon running and a D-Bus session.
Within org.freedesktop.UDisks namespace you can find the object that represents this drive (say org/freedekstop/UDisks/devices/sdb/. It implements org.freedesktop.UDisks.interface. This interface has all the properties that you can dream of, including UUID (IdUuid), FAT label (IdLabel), all the details about filesystem, SMART status (if the drive supports that) etc. etc.
How to use D-Bus API in C is a topic for another question. I assume that's been already discussed in detail -- just search [dbus] and [c] tags.
Flash drives are generally FAT32, which means the "name" that you're looking for is probably the FAT drive label. The most common linux command to retrieve that information is mlabel from the mtools package.
The command looks like this:
[root#localhost]$ mlabel -i /dev/sde1 -s ::
Volume label is USB-DISK
This program works by reading the raw FAT header of the filesystem and retrieving the label from that data. You can look at the source code for the applciation to see how you can replicate the parsing of FAT data in your own application... or you can simply execute run the mlabel binary and read the result into your program. The latter sounds simpler to me.
To call the methods:
kernResult = self->FindEjectableCDMedia(&mediaIterator);
if (KERN_SUCCESS != kernResult) {
printf("FindEjectableCDMedia returned 0x%08x\n", kernResult);
}
kernResult = self->GetPath(mediaIterator, bsdPath, sizeof(bsdPath));
if (KERN_SUCCESS != kernResult) {
printf("GetPath returned 0x%08x\n", kernResult);
}
and the methods:
// Returns an iterator across all DVD media (class IODVDMedia). Caller is responsible for releasing
// the iterator when iteration is complete.
kern_return_t ScanPstEs::FindEjectableCDMedia(io_iterator_t *mediaIterator)
{
kern_return_t kernResult;
CFMutableDictionaryRef classesToMatch;
// CD media are instances of class kIODVDMediaTypeROM
classesToMatch = IOServiceMatching(kIODVDMediaClass);
if (classesToMatch == NULL) {
printf("IOServiceMatching returned a NULL dictionary.\n");
} else {
CFDictionarySetValue(classesToMatch, CFSTR(kIODVDMediaClass), kCFBooleanTrue);
}
kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, mediaIterator);
return kernResult;
}
// Given an iterator across a set of CD media, return the BSD path to the
// next one. If no CD media was found the path name is set to an empty string.
kern_return_t GetPath(io_iterator_t mediaIterator, char *Path, CFIndex maxPathSize)
{
io_object_t nextMedia;
kern_return_t kernResult = KERN_FAILURE;
DADiskRef disk = NULL;
DASessionRef session = NULL;
CFDictionaryRef props = NULL;
char * bsdPath = '\0';
*Path = '\0';
nextMedia = IOIteratorNext(mediaIterator);
if (nextMedia) {
CFTypeRef bsdPathAsCFString;
bsdPathAsCFString = IORegistryEntryCreateCFProperty(nextMedia,CFSTR(kIOBSDNameKey),kCFAllocatorDefault,0);
if (bsdPathAsCFString) {
//strlcpy(bsdPath, _PATH_DEV, maxPathSize);
// Add "r" before the BSD node name from the I/O Registry to specify the raw disk
// node. The raw disk nodes receive I/O requests directly and do not go through
// the buffer cache.
//strlcat(bsdPath, "r", maxPathSize);
size_t devPathLength = strlen(bsdPath);
if (CFStringGetCString( (CFStringRef)bsdPathAsCFString , bsdPath + devPathLength,maxPathSize - devPathLength, kCFStringEncodingUTF8)) {
qDebug("BSD path: %s\n", bsdPath);
kernResult = KERN_SUCCESS;
}
session = DASessionCreate(kCFAllocatorDefault);
if(session == NULL) {
qDebug("Can't connect to DiskArb\n");
return -1;
}
disk = DADiskCreateFromBSDName(kCFAllocatorDefault, session, bsdPath);
if(disk == NULL) {
CFRelease(session);
qDebug( "Can't create DADisk for %s\n", bsdPath);
return -1;
}
props = DADiskCopyDescription(disk);
if(props == NULL) {
CFRelease(session);
CFRelease(disk);
qDebug("Can't get properties for %s\n",bsdPath);
return -1;
}
CFStringRef daName = (CFStringRef )CFDictionaryGetValue(props, kDADiskDescriptionVolumeNameKey);
CFStringGetCString(daName,Path,sizeof(Path),kCFStringEncodingUTF8);
if(daName) {
qDebug("%s",Path);
CFRetain(daName);
}
CFRelease(daName);
CFRelease(props);
CFRelease(disk);
CFRelease(session);
CFRelease(bsdPathAsCFString);
}
IOObjectRelease(nextMedia);
}
return kernResult;
}

Resources