Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

unauthorized access with LiteDB[BUG] in database in mode share #1992

Open
AliAbuHilu opened this issue Apr 22, 2021 · 3 comments
Open

unauthorized access with LiteDB[BUG] in database in mode share #1992

AliAbuHilu opened this issue Apr 22, 2021 · 3 comments
Labels

Comments

@AliAbuHilu
Copy link

Version
Which LiteDB LiteDB" Version="5.0.10" / Windows 10 /.NET framework 4.5 are you using. (REQUIRED)

Describe the bug
I'm not getting access to the database when the application is not an administrator , database in mode share

Code to Reproduce
private LiteDB.ConnectionString configConnection;
string strConnection = @"c:\RegStatusMonitor\RegStatusMonitor.db";

if (!Directory.Exists(strConnection))
{
	Directory.CreateDirectory(strConnection);
}
configConnection = new ConnectionString
{
	Filename = strConnection,
	Password = strContato,
	Connection = ConnectionType.Shared
};

using (var db = new LiteDatabase(configConnection))
{


	var colEnvio = db.GetCollection<Model.MonitoramentoEnvio>("MonitoramentoEnvio");

	// cria instânica de monitoramento Envio
	Model.MonitoramentoEnvio MonitoramentoEnvio = new Model.MonitoramentoEnvio
	{
	idDispositvo = _config.eqpIdDispositivo,
	campo = codigo_status,
	valor = valor_status,
	data = data_mudanca,
	cavId = iCavid
	};

	ret = colEnvio.Insert(MonitoramentoEnvio);

}	

Expected behavior
record saved successfully when user is not administrator in shared mode

Screenshots/Stacktrace
Failed to Record Record - [10], [System.UnauthorizedAccessException: Access to the path 'Global \ FFBAB3EC7319D08E60E44B4EA5FA83570C27F817.Mutex' was denied. || in System.IO .__ Error.WinIOError (Int32 errorCode, String maybeFullPath) || in System.Threading.Mutex.MutexTryCodeHelper.MutexTryCode (Object userData) || in System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup (TryCode code, CleanupCode backoutCode, Object userData) || in System.Threading.Mutex.CreateMutexWithGuaranteedCleanup (Boolean initiallyOwned, String name, Boolean & createdNew, SECURITY_ATTRIBUTES secAttrs) || in System.Threading.Mutex..ctor (Boolean initiallyOwned, String name, Boolean & createdNew, MutexSecurity mutexSecurity) || in LiteDB.SharedEngine..ctor (EngineSettings settings) || in LiteDB.ConnectionString.CreateEngine () || in LiteDB.LiteDatabase..ctor (ConnectionString connectionString, BsonMapper mapper) || in RegStatusMonitor.Status.gravaPing (Int32 codigo_status, String valor_status)]

Additional context
this is a dll component that will be accessed by several non-administrator users

@AliAbuHilu AliAbuHilu added the bug label Apr 22, 2021
@escherrer
Copy link

I'm also running into this. I'm using LiteDB to log requests in a web.api app. Strangely it only happens in an Azure App Service, and doesn't have this issue when running in IIS. Both are running .Net 4.8. LiteDB is v5.0.10.

First I get UnauthorizedAccessException:

2021-04-23 00:00:11.8705|ERROR|RSSProxy.Controllers.CLSController|System.UnauthorizedAccessException: Access to the path is denied.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.__Error.WinIOError()
at System.IO.FileStream.FlushOSBuffer()
at System.IO.FileStream.Flush(Boolean flushToDisk)
at LiteDB.StreamExtensions.FlushToDisk(Stream stream)
at LiteDB.Engine.DiskService.Write(IEnumerable`1 pages, FileOrigin origin)
at LiteDB.Engine.WalIndexService.CheckpointInternal()
at LiteDB.Engine.WalIndexService.TryCheckpoint()
at LiteDB.Engine.LiteEngine.Dispose(Boolean disposing)
at LiteDB.Engine.LiteEngine.Dispose()
at LiteDB.LiteDatabase.Dispose(Boolean disposing)
at LiteDB.LiteDatabase.Dispose()
at RSSProxy.DataAccess.AdDataAccess.SaveProxyRequest(ProxyRequest proxyRequest) in D:\a\1\s\src\RSSProxy\DataAccess\AdDataAccess.cs:line 123
at RSSProxy.Controllers.CLSController.LogProxyRequest(String destination, HttpStatusCode httpStatusCode) in D:\a\1\s\src\RSSProxy\Controllers\CLSController.cs:line 300
at RSSProxy.Controllers.CLSController.Get(String destination) in D:\a\1\s\src\RSSProxy\Controllers\CLSController.cs:line 249

Then I get IOException for every request thereafter:

2021-04-23 00:00:13.7924|ERROR|RSSProxy.Controllers.CLSController|System.IO.IOException: The process cannot access the file 'D:\home\data\Ad.db' because it is being used by another process.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
at LiteDB.Engine.FileStreamFactory.GetStream(Boolean canWrite, Boolean sequencial)
at LiteDB.Engine.StreamPool.<>c__DisplayClass3_0.<.ctor>b__0()
at System.Lazy1.CreateValue() at System.Lazy1.LazyInitValue()
at System.Lazy`1.get_Value()
at LiteDB.Engine.DiskService..ctor(EngineSettings settings, Int32[] memorySegmentSizes)
at LiteDB.Engine.LiteEngine..ctor(EngineSettings settings)
at LiteDB.ConnectionString.CreateEngine()
at LiteDB.LiteDatabase..ctor(ConnectionString connectionString, BsonMapper mapper)
at RSSProxy.DataAccess.AdDataAccess.GetLiteDatabase() in D:\a\1\s\src\RSSProxy\DataAccess\AdDataAccess.cs:line 38
at RSSProxy.DataAccess.AdDataAccess.SaveProxyRequest(ProxyRequest proxyRequest) in D:\a\1\s\src\RSSProxy\DataAccess\AdDataAccess.cs:line 116
at RSSProxy.Controllers.CLSController.LogProxyRequest(String destination, HttpStatusCode httpStatusCode) in D:\a\1\s\src\RSSProxy\Controllers\CLSController.cs:line 300
at RSSProxy.Controllers.CLSController.Get(String destination) in D:\a\1\s\src\RSSProxy\Controllers\CLSController.cs:line 249

Here is the data access class. It is singleton using Ninject:

using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using LiteDB;
using NLog;

namespace RSSProxy.DataAccess
{
    public class AdDataAccess : IAdDataAccess
    {
        private readonly string _dbLocation;
        private readonly Logger _logger;
        private readonly object _locker = new object();

        public AdDataAccess()
        {
            _logger = LogManager.GetLogger(typeof(AdDataAccess).FullName);
            _logger.Debug("Ctor - Begin");

            string dbFolder = ConfigurationManager.AppSettings["dbLocation"];
            Directory.CreateDirectory(dbFolder);
            _dbLocation = dbFolder + "Ad.db";

            _logger.Debug("Ctor - End: DB location: " + _dbLocation);
        }

        private ILiteDatabase GetLiteDatabase()
        {
            var connString = new ConnectionString
            {
                Filename = _dbLocation,
                Connection = ConnectionType.Direct
            };

            return new LiteDatabase(connString);
        }

        public Ad GetAd(string id)
        {
            lock (_locker)
            {
                _logger.Debug("GetAd - Begin");

                Ad result;
                using (var db = GetLiteDatabase())
                {
                    var col = db.GetCollection<Ad>();
                    result = col.FindById(id);
                }

                _logger.Debug("GetAd - End");

                return result;
            }
        }

        public void SaveAd(Ad ad)
        {
            lock (_locker)
            {
                _logger.Debug("SaveAd - Begin");

                using (var db = GetLiteDatabase())
                {
                    var col = db.GetCollection<Ad>();

                    col.Upsert(ad);
                }

                _logger.Debug("SaveAd - End");
            }
        }

        public int PurgeAds(int daysOld)
        {
            lock (_locker)
            {
                _logger.Debug("PurgeAds - Begin");

                int deleteCount = 0;
                using (var db = GetLiteDatabase())
                {
                    var col = db.GetCollection<Ad>();

                    var oldAds = new List<Ad>();
                    foreach (Ad ad in col.FindAll())
                    {
                        if ((ad.GetLastUpdate().CaptureDateTime - DateTime.UtcNow).TotalDays > daysOld)
                        {
                            oldAds.Add(ad);
                        }
                    }

                    foreach (var oldAd in oldAds)
                    {
                        deleteCount++;
                        col.Delete(oldAd.Id);
                    }

                    _logger.Debug("Ads deleted: {0}", deleteCount);
                }

                _logger.Debug("PurgeAds - End");

                return deleteCount;
            }
        }

        public void SaveProxyRequest(ProxyRequest proxyRequest)
        {
            lock (_locker)
            {
                _logger.Debug("SaveProxyRequest - Begin");

                using (var db = GetLiteDatabase())
                {
                    var col = db.GetCollection<ProxyRequest>();

                    col.Upsert(proxyRequest);
                }

                _logger.Debug("SaveProxyRequest - End");
            }
        }

        public int PurgeProxyRequests()
        {
            lock (_locker)
            {
                _logger.Debug("PurgeProxyRequests - Begin");

                int deleteCount;
                using (var db = GetLiteDatabase())
                {
                    ILiteCollection<ProxyRequest> col = db.GetCollection<ProxyRequest>();

                    var cutoffDate = DateTime.UtcNow.AddDays(-2);
                    deleteCount = col.DeleteMany(x => x.RequestDateTime < cutoffDate);

                    _logger.Debug(deleteCount + " old requests deleted");
                }

                _logger.Debug("PurgeProxyRequests - End");

                return deleteCount;
            }
        }

        public List<ProxyRequest> GetProxyRequests()
        {
            lock (_locker)
            {
                _logger.Debug("GetProxyRequests - Begin");

                List<ProxyRequest> result;

                using (var db = GetLiteDatabase())
                {
                    ILiteCollection<ProxyRequest> col = db.GetCollection<ProxyRequest>();
                    result = col.FindAll().ToList();
                }

                _logger.Debug("GetProxyRequests - End");

                return result;
            }
        }
    }

@rexcardan
Copy link

I just put in a PR with the fix. Can you try it: #1998

@adamdriscoll
Copy link

I was also able to work around this in an Azure App Service with my change mentioned here: #1622 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants